!!(new Boolean(false)) #wtfjsThe result of the above expression is true. Let us first learn about coercion in JavaScript. We can then use that knowledge to understand this result.
Coercion
Many operators and functions in JavaScript expect their arguments to have certain types. If they don’t, they are coerced (converted) to those types. Coercing an object to a primitive type is a two-step process: First, the object is converted to a primitive. Then, if necessary, the primitive is converted to the correct type. Two methods are used to convert an object to a primitive:- valueOf()
- toString()
- “Number”: you expect the value to be a number.
- “String”: you expect the value to be a string.
- “Default”: you don’t have any expectations for the value.
Let’s try out coercion via the following object:
var obj = {
valueOf: function () {
console.log("valueOf");
return '0';
},
toString: function () {
console.log("toString");
return 1;
}
};
Coercing to number
There are two common ways for coercing to number: the unary plus operator and Number, used as a function (not as a constructor).
> +obj
valueOf
0
> Number(obj)
valueOf
0
In both cases, things work as expected: the number algorithm is used. Then the result returned by valueOf() is converted to number.
Coercing to string
Two common ways of coercing a value to string are: the binary plus operator where one operand is a string and String, used as a function (not as a constructor).
> ''+obj
valueOf
'0'
> String(obj)
toString
'1'
The binary plus operator uses the default algorithm, because one can add either numbers or strings.
Coercing to boolean
Two ways of coercing to boolean are: using the unary negation operator twice (once converts to boolean and negates) or using Boolean as a function.
> !!obj
true
> Boolean(obj)
true
Here we see that objects are never converted to primitive. The rule is simply: any object is always true. For primitives, only the following values are coerced to false, all other values are coerced to true.
- undefined
- null
- false
- +0, -0, NaN
- ""
Understanding the initial result
Now it should be obvious why !!(new Boolean(false)) evaluates to true: Any instance of Boolean is always an object and those are always coerced to true.Recommendations
Here are a few recommendations for coercion and objects:- Stay away from instances of Boolean, Number and String. You don’t normally need or encounter them in JavaScript.
- However, I do like using Boolean, Number and String as functions, to coerce values. They are nicely descriptive when used in this manner.
- Obviously, all of the above ways of coercing to primitives work for any value, not just for objects:
> Number("123") 123 > Boolean(0) false > String(true) 'true' - One does not often coerce objects to primitives. Doing so is, however, good for many WTFs [1] and hacks [2].
Further reading
- What is {} + {} in JavaScript? [Describes the binary plus operator and the conversion to number and string in detail]
- Fake operator overloading in JavaScript [a fun hack involving objects being coerced to numbers]
- JavaScript’s two zeros
1 comment:
“The rule is simply: any object is always tru[thy].”
There’s an interesting exception to this rule in the DOM: `document.all` is a falsy object. I talk a little bit about it around 34:00 in http://vimeo.com/52851509, if you’re interested.
Post a Comment