JS Value Objects – 3. Integer data type

Note: This is the third post in a series about the use of Value Objects in JavaScript.

In the previous posts we introduced ourselfs to the concept of the Value Object design pattern and the way JavaScript implements data types (or value types) In this post we will start building our own value object in JS: the integer.

Reverse engeneering

Now let’s try if we can create an object that behaves the same way as the String object we inspected in the previous post.

We create a constructor called MyString, accepting a value, and give it the method valueOf in its prototype. The valueOf method is in fact overwriting the default one defined in Object.prototype, which all objects inherit from. This method is called whenever JavaScript tries to perform a binary operation on an object. For example when comparing (==) or joining (+) strings. Now lets run the same tests again on this new object:

So far, so good. We have similar results for these tests. But let’s be honest, we did not recreate the String object and that’s also not what we want to achieve. What we did do, is getting to know how you might create your own data types, or Value Objects.

Integer data type

An interesting thing about JavaScript is that it does not have an Integer data type. It has Number, representing all numerical values, but if we want to be sure that there is no fractional component we need to check it whenever we need to. To make our lives easier we will create our own Integer object instead:

This Value Object embodies the new data type: Integer. It can not be instantiated with an invalid value (we still want the value to be a number) and it can, because of the valueOf method, still be used in calculations:

When you instantiate a new String, Boolean, Number, etc without passing an argument, the object will get a default value (respectively “”, false, 0). This might not always be necessary, but lets say in our case it is preferable.

Note: To check if the value was passed you might be used to check if the value is falsable (but of course the passed value might be 0) or check if value is strictly equal to undefined, but that would mean you can not instantiate an Integer with undefined. I don’t know if you would be needing to, but still, this is the most valid way to check if really no argument was passed.

Parsing input

Another thing noticeable is that all native data type objects will never fail on no matter what input you would pass them.

String will always try to cast the input to a string which, in the worst case, will lead to “[object Object]”-like values, a Number will use the value NaN (Not a Number) whenever it can’t handle the input, a Boolean can cast all types of input, because if it is not falseable it is true and an Array will take its arguments as items in its list (just like the literal version []).

The Object-object treats its input with even more care. When you pass a string as a value it will create a string for you and returns the same result as you would get when creating a string with the String-object. The same counts for Number, Boolean, Array and even RegExp. In fact, if you pass it an object it will just return it back untouched.

In our case we would also like to be able to pass a value as a string. Maybe not as part of a sentence (like you would do with parseInt), but a value like “3” or “-12” should be possible. Beside that, it would also be nice if it would round a float to an integer.

When we multiply the value by one, JavaScript will first try to cast the value to a number and then multiply it by 1, resulting in either a valid number or NaN. When trying to round NaN to the nearest whole number the value will stay NaN, which will trow an exception on validation.

Immutability

But wait! We can still change the value of the object!

We said in the first post that values have to be immutable. Values do not change, they simply get assigned to variables and removed if another value is assigned. Luckily JS provides us a way to assign properties in a way that they can not be changed.

Methods

Objects can have methods. Those functions can help us to interact with the value. The String object for instance has a method called toUppercase which will return a new all uppercase string of the original value. It is important to understand that this produces a new string and does not change the original string, because value objects are immutable.

In our case we might want to have a toFixed method that will produce a string created from the original value with a fixed number of decimals. Methods can be created on the prototype object, just like the valueOf function.

This will let us do whatever we want, but we have to keep ourselfs in control by making sure we doe not change the value itself.

The method in this example already exists on the Number object with exactly the same purpose. An integer and number (float) are much alike actaully, so why dont we just copy all methods in the Number prototype to the Integer prototype? Well, we cannot just copy paste as-is because the methods probably expect a certain internal structure and behaviour that is different in the Integer object. Instead we have to call the methods on the actual value by wrapping them into function.

Summary

Hurray! We created our first value object! By taking the Integer as an example we saw how a constructor can be used and tweaked to create an object that can pass as a value object. An object that is immutable and, as long as its value is not an object itself, cannot be referenced.

There is only one important part missing: The life cycle. Integers with the same value are not equal to each other, because both are objects and objects are unique.

In the next post we will take a closer look to this problem and I will write some more practical examples.

JS Value Objects – 2. Data types

Note: This is the second post in a series about the use of Value Objects in JavaScript.

In the previous post we learned what a Value Object (VO) is and what kind of problems it can solve. Now we can start exploring the possibilities in JavaScript (JS) for creating a similar pattern. In this post we will start with a brief view at data types.

Literals vs. Objects

JS provides 6 different basic types of values: numbers, strings, Booleans, objects, functions and undefined values (null and undefined).

Those primitives, with the exception of null and undefined, can be created from literals or from a constructor. The difference between those two methods of instantiating is not only the syntax, but also the actual value that it will produce. When using the loose equality operator you might not see this, but when you would compare the different methods with strict equality you will see that the value created from the constructor is an object and not a string (or number or Boolean).

This is a minor downside, but you should use the strict equality operator with care anyway. Another side-effect is that creating strings as objects is slower than creating it from literals. In general I would advice to use the literal way as much as possible.

Of course this does not count for objects, because an object is always only equal to itself. I will leave the  data type ‘function’ out of this discussion because they have a very special, multifunctional role in JS.

Note: Arrays are also objects and therefor not a primitive data type in JS. You can check this by using unary ‘typeof’ keyword.

Are Data Types Value Objects?

In the previous post we came across the 4 key properties of a VO: single concept, no life cycle, immutable and can not be referenced. Do these rules apply to the JS primitive data types?

Single concept

This rule most certainly applies. Just as much as in any other programming language. At least, for string, number, Boolean, object and function. Null is a bit of a strange value because it actually means that there is no value set and undefined is in fact nothing at all; it is, if one could say so, a not found value.

No lifecycle

For this rule it cannot be said just as easily, because it would mean that there could be only one ‘instance’ of every value that a data type could have. That is partly true:

According to this, we can conclude that strings created from literals do apply to the no life cycle rule, but strings created from objects do not. They have some kind of unique identifier that makes each instance different from another instance with exactly the same value. This is important to notice, because it conflicts with the description Eric Evans gave us in the first post; this is even better described by Martin Fowler:

Value Objects … their notion of equality isn’t based on identity, instead two value objects are equal if all their fields are equal. – Martin Fowler

We can test that this is not true for objects:

Note: Interesting is that we can compare objects if we convert both of them to a JSON string. This has a lot of limitations though; The objects can not contain methods (functions) and the order of the properties should be exactly the same.

Immutable

Immutability is also partly true for JS data types. As strings, numbers and Booleans cannot be mutated, objects can:

No refference

Another characteristic of objects is that they are always referenced and although it can give you a lot of headaches, this is actually one of the things that makes JS a special language. Referencing has a lot of benefits; it gives you a lot of freedom, but it also provides a door to hell where it causes nasty side-effects that are hard to trace back.

In the above example we see that John and Peter live in the same house, but when Peter moves and we try to change his address, we also change John’s address.

Summary

Taking this all into account, you could say that the literals for creating a string, number, boolean, null and undefined are real values, because they have the key properties. Object on the other hand is failing for at least 3 of the 4 rules, because you might also argue if object is even describing a single concept.

The funny part is that in the next post we will find out that we have to use objects to be able to create our own VOs. So stay tuned!

Further reading