Understanding type coercion in JavaScript - javascript

I know == operator performs the type coercion. But I can't understand the below behaviour.
const x = new Boolean(false);
if (x) {
console.log("if(x) is true");
}
if (x == false) {
console.log("if(x == false) is true");
}
Surprisingly, above snippet prints both lines:
if(x) is true
if(x == false) is true
Can someone explain this weird behaviour or there is something fundamental I'm missing?

As mentioned by other answers, that's because x is an Object – a Boolean object, but still an object, since you're using the new operator – and is coerced only when you compare x to false: the if (x) is checking if x is a truthy value, and therefore doesn't need coercion (there are no other operands involved): an object is always "true" (weeeell… almost always: typeof null returns object but it's a falsy value. But that's another story…).
You can easily checking when the coercion is invoked tapping the toPrimitive symbol:
var x = new Boolean(false);
// first of all, if it wasn't an object you couldn't
// do this
x[Symbol.toPrimitive] = function(hint) {
console.log({hint});
return this.valueOf();
}
// no console.log yet
if (x) {
console.log("if(x) is true");
}
// here you got the console.log before the one
// inside the block, since the coercion happens
// in the `if`
if (x == false) {
console.log("if(x == false) is true");
}

new Boolean(false) produces an object. Objects are always truthy even if they wrap a falsy primitive value. For example, new String("") is also truthy despite "" being falsy.
On the other hand, when you do new Boolean(false) == false, it coerces the object to its primitive value for the comparison. Incidentally, new Boolean(false) === false is not true, since their types don't match.
As a general rule, you shouldn't use object constructors for primitive types unless you have a specific reason for it, to avoid unexpected behavior like this.

when you do if (expression) in javascript the expression is evaluated by being cast to a boolean.
Somewhat confusingly, Boolean(new Boolean(false)) evaluates to true because as Nick said it is still an object. This is what is causing the behaviour you're confused about.
Good read for more info https://javascriptweblog.wordpress.com/2011/02/07/truth-equality-and-javascript/

If you write
const x = new Boolean(false);
typeof x will return object. The type object is "truthy", which means it evaluates to true if there's no operator like ==. However, the value of it is false, which is why the second statement evaluates to true as well.
So the if statements behave differently, because the if without operator checks whether the type is truthy or falsy (in this case truthy -> true) and the if with the comparison (==) calls .valueOf() which is false.
You shouldn't be using new wrappers for this scenario anyway.
const x = false;
is enough. For casting, you can use Boolean() without new wrapper.
To check whether a value is truthy, you can use a double negation:
const x = new Boolean(false);
if (x) console.log(!!x);
if (x == false) console.log(x.valueOf());

You should be using Boolean(false) instead of new Boolean(false), since Boolean is a function.
Otherwise you get an empty object {}, which is not the same type as what is returned by the function itself, which is a boolean.
const x = new Boolean(false);
const y = Boolean(false);
console.log(x, typeof x);
console.log(y, typeof y);
In the your first test, you only check if the value is truthy, and an empty object is truthy, since x = {}, the test passes:
const x = new Boolean(false);
console.log(x, !!x, !!{}, Boolean(x))
if (x) {
console.log("if(x) is true");
}
However, when using ==, the operator coerces new Boolean(false) to its primitive value using x.valueOf which is false and thus the equality passes.
const x = new Boolean(false);
console.log(x.valueOf())

Related

Logical NOT on Boolean Object always return false in Javascript [duplicate]

This question already has answers here:
Why does !new Boolean(false) equals false in JavaScript?
(2 answers)
Closed 6 years ago.
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.
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>
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.
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
}
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.
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.

OR logical operator when set a variable on javascript [duplicate]

I am debugging some JavaScript and can't explain what this || does:
function (title, msg) {
var title = title || 'Error';
var msg = msg || 'Error on Request';
}
Why is this guy using var title = title || 'ERROR'? I sometimes see it without a var declaration as well.
What is the double pipe operator (||)?
The double pipe operator (||) is the logical OR operator . In most languages it works the following way:
If the first value is false, it checks the second value. If that's true, it returns true and if the second value is false, it returns false.
If the first value is true, it always returns true, no matter what the second value is.
So basically it works like this function:
function or(x, y) {
if (x) {
return true;
} else if (y) {
return true;
} else {
return false;
}
}
If you still don't understand, look at this table:
| true false
------+---------------
true | true true
false | true false
In other words, it's only false when both values are false.
How is it different in JavaScript?
JavaScript is a bit different, because it's a loosely typed language. In this case it means that you can use || operator with values that are not booleans. Though it makes no sense, you can use this operator with for example a function and an object:
(function(){}) || {}
What happens there?
If values are not boolean, JavaScript makes implicit conversion to boolean. It means that if the value is falsey (e.g. 0, "", null, undefined (see also All falsey values in JavaScript)), it will be treated as false; otherwise it's treated as true.
So the above example should give true, because empty function is truthy. Well, it doesn't. It returns the empty function. That's because JavaScript's || operator doesn't work as I wrote at the beginning. It works the following way:
If the first value is falsey, it returns the second value.
If the first value is truthy, it returns the first value.
Surprised? Actually, it's "compatible" with the traditional || operator. It could be written as following function:
function or(x, y) {
if (x) {
return x;
} else {
return y;
}
}
If you pass a truthy value as x, it returns x, that is, a truthy value. So if you use it later in if clause:
(function(x, y) {
var eitherXorY = x || y;
if (eitherXorY) {
console.log("Either x or y is truthy.");
} else {
console.log("Neither x nor y is truthy");
}
}(true/*, undefined*/));
you get "Either x or y is truthy.".
If x was falsey, eitherXorY would be y. In this case you would get the "Either x or y is truthy." if y was truthy; otherwise you'd get "Neither x nor y is truthy".
The actual question
Now, when you know how || operator works, you can probably make out by yourself what does x = x || y mean. If x is truthy, x is assigned to x, so actually nothing happens; otherwise y is assigned to x. It is commonly used to define default parameters in functions. However, it is often considered a bad programming practice, because it prevents you from passing a falsey value (which is not necessarily undefined or null) as a parameter. Consider following example:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
It looks valid at the first sight. However, what would happen if you passed false as flagA parameter (since it's boolean, i.e. can be true or false)? It would become true. In this example, there is no way to set flagA to false.
It would be a better idea to explicitly check whether flagA is undefined, like that:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Though it's longer, it always works and it's easier to understand.
You can also use the ES6 syntax for default function parameters, but note that it doesn't work in older browsers (like IE). If you want to support these browsers, you should transpile your code with Babel.
See also Logical Operators on MDN.
It means the title argument is optional. So if you call the method with no arguments it will use a default value of "Error".
It's shorthand for writing:
if (!title) {
title = "Error";
}
This kind of shorthand trick with boolean expressions is common in Perl too. With the expression:
a OR b
it evaluates to true if either a or b is true. So if a is true you don't need to check b at all. This is called short-circuit boolean evaluation so:
var title = title || "Error";
basically checks if title evaluates to false. If it does, it "returns" "Error", otherwise it returns title.
If title is not set, use 'ERROR' as default value.
More generic:
var foobar = foo || default;
Reads: Set foobar to foo or default.
You could even chain this up many times:
var foobar = foo || bar || something || 42;
Explaining this a little more...
The || operator is the logical-or operator. The result is true if the first part is true and it is true if the second part is true and it is true if both parts are true. For clarity, here it is in a table:
X | Y | X || Y
---+---+--------
F | F | F
---+---+--------
F | T | T
---+---+--------
T | F | T
---+---+--------
T | T | T
---+---+--------
Now notice something here? If X is true, the result is always true. So if we know that X is true we don't have to check Y at all. Many languages thus implement "short circuit" evaluators for logical-or (and logical-and coming from the other direction). They check the first element and if that's true they don't bother checking the second at all. The result (in logical terms) is the same, but in terms of execution there's potentially a huge difference if the second element is expensive to calculate.
So what does this have to do with your example?
var title = title || 'Error';
Let's look at that. The title element is passed in to your function. In JavaScript if you don't pass in a parameter, it defaults to a null value. Also in JavaScript if your variable is a null value it is considered to be false by the logical operators. So if this function is called with a title given, it is a non-false value and thus assigned to the local variable. If, however, it is not given a value, it is a null value and thus false. The logical-or operator then evaluates the second expression and returns 'Error' instead. So now the local variable is given the value 'Error'.
This works because of the implementation of logical expressions in JavaScript. It doesn't return a proper boolean value (true or false) but instead returns the value it was given under some rules as to what's considered equivalent to true and what's considered equivalent to false. Look up your JavaScript reference to learn what JavaScript considers to be true or false in boolean contexts.
|| is the boolean OR operator. As in JavaScript, undefined, null, 0, false are considered as falsy values.
It simply means
true || true = true
false || true = true
true || false = true
false || false = false
undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"
Basically, it checks if the value before the || evaluates to true. If yes, it takes this value, and if not, it takes the value after the ||.
Values for which it will take the value after the || (as far as I remember):
undefined
false
0
'' (Null or Null string)
Whilst Cletus' answer is correct, I feel more detail should be added in regards to "evaluates to false" in JavaScript.
var title = title || 'Error';
var msg = msg || 'Error on Request';
Is not just checking if title/msg has been provided, but also if either of them are falsy. i.e. one of the following:
false.
0 (zero)
"" (empty string)
null.
undefined.
NaN (a special Number value meaning Not-a-Number!)
So in the line
var title = title || 'Error';
If title is truthy (i.e., not falsy, so title = "titleMessage" etc.) then the Boolean OR (||) operator has found one 'true' value, which means it evaluates to true, so it short-circuits and returns the true value (title).
If title is falsy (i.e. one of the list above), then the Boolean OR (||) operator has found a 'false' value, and now needs to evaluate the other part of the operator, 'Error', which evaluates to true, and is hence returned.
It would also seem (after some quick firebug console experimentation) if both sides of the operator evaluate to false, it returns the second 'falsy' operator.
i.e.
return ("" || undefined)
returns undefined, this is probably to allow you to use the behavior asked about in this question when trying to default title/message to "". i.e. after running
var foo = undefined
foo = foo || ""
foo would be set to ""
Double pipe stands for logical "OR". This is not really the case when the "parameter not set", since strictly in JavaScript if you have code like this:
function foo(par) {
}
Then calls
foo()
foo("")
foo(null)
foo(undefined)
foo(0)
are not equivalent.
Double pipe (||) will cast the first argument to Boolean and if the resulting Boolean is true - do the assignment, otherwise it will assign the right part.
This matters if you check for unset parameter.
Let's say, we have a function setSalary that has one optional parameter. If the user does not supply the parameter then the default value of 10 should be used.
If you do the check like this:
function setSalary(dollars) {
salary = dollars || 10
}
This will give an unexpected result for a call like:
setSalary(0)
It will still set the 10 following the flow described above.
Double pipe operator
This example may be useful:
var section = document.getElementById('special');
if(!section){
section = document.getElementById('main');
}
It can also be:
var section = document.getElementById('special') || document.getElementById('main');
To add some explanation to all said before me, I should give you some examples to understand logical concepts.
var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true
It means if the left side evaluated as a true statement it will be finished and the left side will be returned and assigned to the variable. in other cases the right side will be returned and assigned.
And operator have the opposite structure like below.
var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh
Quote: "What does the construct x = x || y mean?"
Assigning a default value.
This means providing a default value of y to x,
in case x is still waiting for its value but hasn't received it yet or was deliberately omitted in order to fall back to a default.
And I have to add one more thing: This bit of shorthand is an abomination. It misuses an accidental interpreter optimization (not bothering with the second operation if the first is truthy) to control an assignment. That use has nothing to do with the purpose of the operator. I do not believe it should ever be used.
I prefer the ternary operator for initialization, for example,
var title = title?title:'Error';
This uses a one-line conditional operation for its correct purpose. It still plays unsightly games with truthiness but, that's JavaScript for you.

Perk in evaluation of Boolean variables in JavaScript?

I have this slightly peculiar situation, a boolean statement I have is giving me two different evaluations, in the alert and if operator.
var test = new Boolean(homePageNonActive && ((firstTime && homePageHash) || (!firstTime && !homePageHash)));
alert(homePageNonActive && ((firstTime && homePageHash) || (!firstTime && !homePageHash))); // GIVES ME FALSE
alert(test); // GIVES ME TRUE ??? WHY?
if(test){
alert(homePageNonActive); // GIVES ME TRUE
alert(firstTime); // GIVES ME TRUE
alert(homePageHash); // GIVES ME FALSE
}
Everything seems to work just fine as long as you use boolean primitives.
But the issue is that you are mixing Boolean objects (homePageHash) with boolean primitives (homePageNonActive and firstTime). The reason why test is "true" is because a "Boolean object false" is "truthy".
Boolean object is not the same as a boolean primitive.
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.
var x = new Boolean(false),
y = false;
if (x) {/*this code is executed*/}
if (y) {/*this code is NOT executed*/}

new Number() vs Number()

What is the difference between new Number() and Number()? I get that new Number() creates a Number object and Number() is just a function, but when should I call which, and why?
On a related note, Mozilla says:
Do not use a Boolean object to convert a non-boolean value to a boolean value. Instead, use Boolean as a function to perform this task.
x = Boolean(expression); // preferred
x = new Boolean(expression); // don't use
Why is that? I thought the results were the same?
Boolean(expression) will simply convert the expression into a boolean primitive value, while new Boolean(expression) will create a wrapper object around the converted boolean value.
The difference can be seen with this:
// Note I'm using strict-equals
new Boolean("true") === true; // false
Boolean("true") === true; // true
And also with this (thanks #hobbs):
typeof new Boolean("true"); // "object"
typeof Boolean("true"); // "boolean"
Note: While the wrapper object will get converted to the primitive automatically when necessary (and vice versa), there is only one case I can think of where you would want to use new Boolean, or any of the other wrappers for primitives - if you want to attach properties to a single value. E.g:
var b = new Boolean(true);
b.relatedMessage = "this should be true initially";
alert(b.relatedMessage); // will work
var b = true;
b.relatedMessage = "this should be true initially";
alert(b.relatedMessage); // undefined
new Number( x )
creates a new wrapper object. I don't think that there is a valid reason to ever use this.
Number( x )
converts the passed argument into a Number value. You can use this to cast some variable to the Number type. However this gets the same job done:
+x
Generally:
You don't need those:
new Number()
new String()
new Boolean()
You can use those for casting:
Number( value )
String( value )
Boolean( value )
However, there are simpler solutions for casting:
+x // cast to Number
'' + x // cast to String
!!x // cast to Boolean
Always worth consulting the spec; from Section 15.7.1:
When Number is called as a function rather than as a constructor, it performs a type conversion.
Similarly, using Boolean as a function (15.6.1):
When Boolean is called as a function rather than as a constructor, it performs a type conversion.
...which means that you consult Section 9.2 ("ToBoolean"):
The abstract operation ToBoolean converts its argument to a value of type Boolean according to Table 11:
Undefined = false
Null = false
Boolean = The result equals the input argument (no conversion).
Number = The result is false if the argument is +0, −0, or NaN; otherwise the result is true.
String = The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
Object = true
The difference between new Boolean(value) and Boolean(value) is basically that the former returns an object, but the latter returns a primitive per the above. This matters, because objects are truthy:
var b = new Boolean(false);
display(b); // Displays "false"
if (b) {
display("true"); // This is the path that gets taken, displaying "true"
}
else {
display("false"); // This path does NOT get taken
}
Live example ...whereas you almost always want booleans for the purpose of testing them.
case with instanceof
const a = new Number('123'); // a === 123 is false
const b = Number('123'); // b === 123 is true
a instanceof Number; // is true
b instanceof Number; // is false
// Type conversion to primitive value
const a = Number('42')
a === 42 // true
a.answer = 'You asked the wrong question'
a.answer // undefined
// Object
const b = new Number('42')
b === 42 // false
b.answer = 'Life, the Universe, and Everything'
b.valueOf() === 42 // true
b.answer // 'Life, the Universe, and Everything'

What does the construct x = x || y mean?

I am debugging some JavaScript and can't explain what this || does:
function (title, msg) {
var title = title || 'Error';
var msg = msg || 'Error on Request';
}
Why is this guy using var title = title || 'ERROR'? I sometimes see it without a var declaration as well.
What is the double pipe operator (||)?
The double pipe operator (||) is the logical OR operator . In most languages it works the following way:
If the first value is false, it checks the second value. If that's true, it returns true and if the second value is false, it returns false.
If the first value is true, it always returns true, no matter what the second value is.
So basically it works like this function:
function or(x, y) {
if (x) {
return true;
} else if (y) {
return true;
} else {
return false;
}
}
If you still don't understand, look at this table:
| true false
------+---------------
true | true true
false | true false
In other words, it's only false when both values are false.
How is it different in JavaScript?
JavaScript is a bit different, because it's a loosely typed language. In this case it means that you can use || operator with values that are not booleans. Though it makes no sense, you can use this operator with for example a function and an object:
(function(){}) || {}
What happens there?
If values are not boolean, JavaScript makes implicit conversion to boolean. It means that if the value is falsey (e.g. 0, "", null, undefined (see also All falsey values in JavaScript)), it will be treated as false; otherwise it's treated as true.
So the above example should give true, because empty function is truthy. Well, it doesn't. It returns the empty function. That's because JavaScript's || operator doesn't work as I wrote at the beginning. It works the following way:
If the first value is falsey, it returns the second value.
If the first value is truthy, it returns the first value.
Surprised? Actually, it's "compatible" with the traditional || operator. It could be written as following function:
function or(x, y) {
if (x) {
return x;
} else {
return y;
}
}
If you pass a truthy value as x, it returns x, that is, a truthy value. So if you use it later in if clause:
(function(x, y) {
var eitherXorY = x || y;
if (eitherXorY) {
console.log("Either x or y is truthy.");
} else {
console.log("Neither x nor y is truthy");
}
}(true/*, undefined*/));
you get "Either x or y is truthy.".
If x was falsey, eitherXorY would be y. In this case you would get the "Either x or y is truthy." if y was truthy; otherwise you'd get "Neither x nor y is truthy".
The actual question
Now, when you know how || operator works, you can probably make out by yourself what does x = x || y mean. If x is truthy, x is assigned to x, so actually nothing happens; otherwise y is assigned to x. It is commonly used to define default parameters in functions. However, it is often considered a bad programming practice, because it prevents you from passing a falsey value (which is not necessarily undefined or null) as a parameter. Consider following example:
function badFunction(/* boolean */flagA) {
flagA = flagA || true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
It looks valid at the first sight. However, what would happen if you passed false as flagA parameter (since it's boolean, i.e. can be true or false)? It would become true. In this example, there is no way to set flagA to false.
It would be a better idea to explicitly check whether flagA is undefined, like that:
function goodFunction(/* boolean */flagA) {
flagA = typeof flagA !== "undefined" ? flagA : true;
console.log("flagA is set to " + (flagA ? "true" : "false"));
}
Though it's longer, it always works and it's easier to understand.
You can also use the ES6 syntax for default function parameters, but note that it doesn't work in older browsers (like IE). If you want to support these browsers, you should transpile your code with Babel.
See also Logical Operators on MDN.
It means the title argument is optional. So if you call the method with no arguments it will use a default value of "Error".
It's shorthand for writing:
if (!title) {
title = "Error";
}
This kind of shorthand trick with boolean expressions is common in Perl too. With the expression:
a OR b
it evaluates to true if either a or b is true. So if a is true you don't need to check b at all. This is called short-circuit boolean evaluation so:
var title = title || "Error";
basically checks if title evaluates to false. If it does, it "returns" "Error", otherwise it returns title.
If title is not set, use 'ERROR' as default value.
More generic:
var foobar = foo || default;
Reads: Set foobar to foo or default.
You could even chain this up many times:
var foobar = foo || bar || something || 42;
Explaining this a little more...
The || operator is the logical-or operator. The result is true if the first part is true and it is true if the second part is true and it is true if both parts are true. For clarity, here it is in a table:
X | Y | X || Y
---+---+--------
F | F | F
---+---+--------
F | T | T
---+---+--------
T | F | T
---+---+--------
T | T | T
---+---+--------
Now notice something here? If X is true, the result is always true. So if we know that X is true we don't have to check Y at all. Many languages thus implement "short circuit" evaluators for logical-or (and logical-and coming from the other direction). They check the first element and if that's true they don't bother checking the second at all. The result (in logical terms) is the same, but in terms of execution there's potentially a huge difference if the second element is expensive to calculate.
So what does this have to do with your example?
var title = title || 'Error';
Let's look at that. The title element is passed in to your function. In JavaScript if you don't pass in a parameter, it defaults to a null value. Also in JavaScript if your variable is a null value it is considered to be false by the logical operators. So if this function is called with a title given, it is a non-false value and thus assigned to the local variable. If, however, it is not given a value, it is a null value and thus false. The logical-or operator then evaluates the second expression and returns 'Error' instead. So now the local variable is given the value 'Error'.
This works because of the implementation of logical expressions in JavaScript. It doesn't return a proper boolean value (true or false) but instead returns the value it was given under some rules as to what's considered equivalent to true and what's considered equivalent to false. Look up your JavaScript reference to learn what JavaScript considers to be true or false in boolean contexts.
|| is the boolean OR operator. As in JavaScript, undefined, null, 0, false are considered as falsy values.
It simply means
true || true = true
false || true = true
true || false = true
false || false = false
undefined || "value" = "value"
"value" || undefined = "value"
null || "value" = "value"
"value" || null = "value"
0 || "value" = "value"
"value" || 0 = "value"
false || "value" = "value"
"value" || false = "value"
Basically, it checks if the value before the || evaluates to true. If yes, it takes this value, and if not, it takes the value after the ||.
Values for which it will take the value after the || (as far as I remember):
undefined
false
0
'' (Null or Null string)
Whilst Cletus' answer is correct, I feel more detail should be added in regards to "evaluates to false" in JavaScript.
var title = title || 'Error';
var msg = msg || 'Error on Request';
Is not just checking if title/msg has been provided, but also if either of them are falsy. i.e. one of the following:
false.
0 (zero)
"" (empty string)
null.
undefined.
NaN (a special Number value meaning Not-a-Number!)
So in the line
var title = title || 'Error';
If title is truthy (i.e., not falsy, so title = "titleMessage" etc.) then the Boolean OR (||) operator has found one 'true' value, which means it evaluates to true, so it short-circuits and returns the true value (title).
If title is falsy (i.e. one of the list above), then the Boolean OR (||) operator has found a 'false' value, and now needs to evaluate the other part of the operator, 'Error', which evaluates to true, and is hence returned.
It would also seem (after some quick firebug console experimentation) if both sides of the operator evaluate to false, it returns the second 'falsy' operator.
i.e.
return ("" || undefined)
returns undefined, this is probably to allow you to use the behavior asked about in this question when trying to default title/message to "". i.e. after running
var foo = undefined
foo = foo || ""
foo would be set to ""
Double pipe stands for logical "OR". This is not really the case when the "parameter not set", since strictly in JavaScript if you have code like this:
function foo(par) {
}
Then calls
foo()
foo("")
foo(null)
foo(undefined)
foo(0)
are not equivalent.
Double pipe (||) will cast the first argument to Boolean and if the resulting Boolean is true - do the assignment, otherwise it will assign the right part.
This matters if you check for unset parameter.
Let's say, we have a function setSalary that has one optional parameter. If the user does not supply the parameter then the default value of 10 should be used.
If you do the check like this:
function setSalary(dollars) {
salary = dollars || 10
}
This will give an unexpected result for a call like:
setSalary(0)
It will still set the 10 following the flow described above.
Double pipe operator
This example may be useful:
var section = document.getElementById('special');
if(!section){
section = document.getElementById('main');
}
It can also be:
var section = document.getElementById('special') || document.getElementById('main');
To add some explanation to all said before me, I should give you some examples to understand logical concepts.
var name = false || "Mohsen"; # name equals to Mohsen
var family = true || "Alizadeh" # family equals to true
It means if the left side evaluated as a true statement it will be finished and the left side will be returned and assigned to the variable. in other cases the right side will be returned and assigned.
And operator have the opposite structure like below.
var name = false && "Mohsen" # name equals to false
var family = true && "Alizadeh" # family equals to Alizadeh
Quote: "What does the construct x = x || y mean?"
Assigning a default value.
This means providing a default value of y to x,
in case x is still waiting for its value but hasn't received it yet or was deliberately omitted in order to fall back to a default.
And I have to add one more thing: This bit of shorthand is an abomination. It misuses an accidental interpreter optimization (not bothering with the second operation if the first is truthy) to control an assignment. That use has nothing to do with the purpose of the operator. I do not believe it should ever be used.
I prefer the ternary operator for initialization, for example,
var title = title?title:'Error';
This uses a one-line conditional operation for its correct purpose. It still plays unsightly games with truthiness but, that's JavaScript for you.

Categories

Resources