Javascript is a language full of surprises: there are the good parts
and the bad parts
. Today, I discovered valueOf. I’ll let you decide to what parts of javascript valueOf
belongs…
A pure function that is not pure
The following interactive code snippet is based on Is Your Javascript function actually pure?.
Have a look at this (simple?) javascript function and ask yourself whether it is a pure function or not.
Does the following function always returns the same result given the same argument?
function sum(arr) {
var z = 0;
for (var i = 0; i < arr.length; i++) {
z += arr[i];
}
return z;
}
If you are like the majority of javascript developers, you probably think that the answer is: YES
.
But the correct answer is: NO
.
Here is the proof:
var arr = [{}, {}, {}];
arr[0].valueOf = arr[1].valueOf = arr[2].valueOf = Math.random;
sum(arr)
Calling sum
another time with the same argument:
sum(arr)
But not the same result.
And once again, for the fun:
sum(arr)
Someone wrote in Reddit that we can also hack the sum
function using Object.defineProperty
. Like this:
arr_with_get = [0,0,0];
arr_with_get.forEach(function(o, i, a) {
Object.defineProperty(a, i, {get:Math.random});
});
And indeed, sum
returns different results with the same input:
sum(arr_with_get)
sum(arr_with_get)
An impossible assertion that is true
Another weird example is shown in Object.prototype.valueOf, Coercion, and Comparison Hackery in JavaScript.
We are going to provide an object that will make the following (impossible) assertion be true
(mysteryObject < 1) && (mysteryObject > 1)
Here is the interactive code snippet for mysteryObject
:
var mysteryObject = (function() {
var cachedValue = -2;
return {
valueOf: function() { return cachedValue += 2; }
};
})();
(mysteryObject < 1) && (mysteryObject > 1)
Conclusion
Did you like it? Does valueOf
belong to the good parts
or to the bad parts
of javascript?
What do you think about the interactive code snippets powered by KLIPSE?