27

Why logical not operator in javascript returns different result between Boolean value and Boolean object? Consider the following example.

!true  // false
!false // true

!(new Boolean(true))  // false
!(new Boolean(false)) // false

From the spec, it says that the value being evaluated converted ToBoolean. ToBoolean will return true if the argument is an Object, and return as is if the argument is a Boolean.

Digging further, ToBoolean also being used in other places like if statement and conditional operator, consider the following example:

var a = (new Boolean(false)) ? "unexpected" : "expected";
console.log(a); // unexpected

The question: is Boolean object an Object, or a Boolean? Should we not evaluate Boolean object as a Boolean?


UPDATE

My question was marked as duplicate question with this. That question doesn't have a satisfactory answers because none answers my question, Is Boolean object an Object, or a Boolean? Should we not evaluate Boolean object as a Boolean?

Simply knowing Boolean object is an object is not enough, why does it even exists and what is the proper way of dealing and/or designing objects with Boolean object still left unanswered.

Community
  • 1
  • 1
O.O
  • 7,179
  • 1
  • 34
  • 32

5 Answers5

32

An object, no matter if it has properties or not, never defaults to false...

new Boolean(true) will return an object not Boolean and !{} is always going to be false as {} is a truthy value (Boolean({}) will be evaluated as true)

While dealing with Boolean factory function, do not create new instance using new (as it will create new instance of Boolean and will return an object)

Boolean(INPUT) will return primitive-Boolean value of the specified expression which could be used for comparison

From docs, The Boolean object is an object wrapper for a boolean value()

Description: The value passed as the first parameter is converted to a boolean value, if necessary. If value is omitted or is 0, -0, null, false, NaN, undefined, or the empty string (""), the object has an initial value of false. All other values, including any object or the string "false", create an object with an initial value of true.

Do not confuse the primitive Boolean values true and false with the true and false values of the Boolean object.

Any object whose value is not undefined or null, including a Boolean object whose value is false, evaluates to true "when passed to a conditional statement."[Reference]

For example, the condition in the following if statement evaluates to true

var x = new Boolean("false");
if (x) {
  console.log('x is true');
}

var y = new Boolean(false);
if (y) {
  console.log('y is true');
}
<script src="http://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
Rayon
  • 36,219
  • 4
  • 49
  • 76
6

Boolean is a function. Depending on the invocation type, it has different behavior in terms of truthy and falsy.

1. Invoking as a simple function

When calling Boolean(value) as a simple function, it verifies if the argument is a falsy (false, null, undefined, '', 0,Nan) or truthy (all other values: object instances, 1, true, etc). This type of invocation returns a boolean primitive type.
It works as expected:

Boolean(null) // prints false
Boolean(0)    // prints false

Boolean({})  // prints true
Boolean(-1)  // prints true

2. Invoking as a constructor

Like any function in JavaScript, Boolean can be invoked as a constructor: var b = new Boolean(value). This invocation type returns a boolean object instance.
This introduces confusing because JavaScript treats object instances as truthy value.

var b = new Boolean(null);

!!b // prints true, because b is an object instance

if (b) { // b evaluates to true
   //executed code 
}

2.1 Why invoking as a constructor is possible

JavaScript allows this constructor invocation to give developer a mechanism to preserve properties creation for a boolean. A primitive boolean type doesn't save properties assigned to it.

var booleanObject = new Boolean(null);
booleanObject.foo = 'bar'; // create a property
booleanObject.foo // prints 'bar'

var booleanPrimitive = false;
booleanPrimitive.foo = 'bar'; // create a property
booleanPrimitive.foo // prints undefined

2.2 How to make the Boolean object work

Nevertheless, new Boolean(value) has a mechanism to do comparison. Like any JavaScript object, it has a method valueOf(), which returns the transformation of the value to a boolean primitive type (true for truthy and false for falsy):

var falsyBoolean = new Boolean(null);
falsyBoolean.valueOf() // prints false, because null is falsy

var truthyBoolean = new Boolean(1);
truthyBoolean.valueOf() // prints true, because 1 is truthy

To make this work in conditionals, it is necessary to avoid any transformations of the boolean object instance into a truthy value. To make this happen, use comparison operator == directly:

var falsyBoolean = new Boolean(null);

falsyBoolean == false ? 'falsy' : 'truthy' // prints expected 'falsy'

if (falsyBoolean == false) { 
  //executed code
}

If an operand in == operator is an object and other a primitive type, JavaScript transforms it into a primitive type, which actually consists in calling the valueOf() method on the boolean object. See more details in this article.

3. How not to get confused

The best rule is to avoid using Boolean as object instances at all. Boolean(value) or !!value is enough to verify the variable truthy state.

Dmitri Pavlutin
  • 18,122
  • 8
  • 37
  • 41
1

From MDN's entry on Boolean:

Any object whose value is not undefined or null, including a Boolean object whose value is false, evaluates to true when passed to a conditional statement.

For example, the condition in the following if statement evaluates to true:

  var x = new Boolean("false");
  if (x) {
    // this code is executed
  }

  var y = new Boolean(false);
  if (y) {
    // this code is also executed
  }
trincot
  • 317,000
  • 35
  • 244
  • 286
1

You will get same result for true and false parameters when using new Boolean(...)

Object-Oriented JavaScript Book, Stoyan Stefanov:

You can convert any value to its Boolean equivalent using a double negation. Understanding how any value converts to a Boolean is important. Most values convert to true with the exception of the following, which convert to false

""
null
undefined
0
NaN
false

So !!{}, !!new Boolean(true), !!new Boolean(false) return always true

This condition (without double negation):

if (new Boolean(true) === true) {

    console.log('this string will never be printed');
}

returns false, because there are different types:

typeof new Boolean(true); // "object"
typeof true; // "boolean"

You have to compare them only by value to get an expected result:

if (new Boolean(true) == true) {

    console.log('Yay!');
}

new Boolean(true) == true; // true
new Boolean(true) === true; // false

Another example:

if (new Boolean(true) === new Boolean(true)) {

    console.log('this string will never be printed')
}

In this case you are trying to compare objects. You will get the same result both with == and === compare operators.

Object-Oriented JavaScript Book, Stoyan Stefanov:

When you compare objects, you'll get true only if you compare two references to the same object. Comparing two distinct objects that happen to have the exact same methods and properties returns false.

Do not use a Boolean object new Boolean(...) in place of a Boolean primitive.

Ali Mamedov
  • 5,116
  • 3
  • 33
  • 47
0

Just tried out the folliwng:

            alert(typeof true);    //alerts boolean
            alert(typeof new Boolean(true));   //alert object
            alert(typeof !(new Boolean(true)));   //alerts boolean
            alert(!(new Boolean(true)));         //alerts false

Both Rayon and Mukul are right, you just need to use !Boolean(false) //returns true as a boolean value.

Kailas
  • 7,350
  • 3
  • 47
  • 63