Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is using && and || to shortcut typeof == "undefined" checks stable in javascript?

Tags:

javascript

Consider the following nested data structure:

var options = {
    option1 = {
        option1a : "foo",
        option1b : "bar"
    },
    option2 = {},
}

I've got a data structure like the one above, which I'm using as a list of optional parameters for inputs to a function. Since all of this is optional inputs, it may or may not exist. Initially, I was using chains of typeof x == "undefined" statements to make sure that, for example, options, option1, and option1a are all defined. My code would end up looking like this for defining a variable:

if(typeof option != "undefined" 
  && typeof option.option1 != "undefined" 
  && typeof option.option1.option1a != "undefined){
    var x = option.option1.option1a;
} else {
    var x = "default";
};

I noticed that I can shorten this to the following:

var x = option && option.option1 && option.option1.option1a || "default";

Does && consistently return the last true or first false statement? And does || consistently return the first true statement? Logic would dictate that they could return booleans in some implementations, but I don't know enough about browser / javascript implementations to make that statement definitively. Is this a safe way to go about doing this, or is there a better way?

like image 648
ckersch Avatar asked Jan 13 '23 12:01

ckersch


1 Answers

Yes that will work correctly. && returns the last true statement or first false statement, || returns the first true statement or last false statement.

var a = false || 0 // a === 0
var b = false && 0 // b === false
var c = true || 1 // c === true
var d = true && 1 // d === 1

and && is evaluated before || so

var e = false || 0 && null // e === null
var f = 1 || 2 && 3 // f === 1

Its also worth mentioning that falsy values encompass more than undefined in JS, so your 2 checks are not quite the same. A value of 0 for instance, will be considered falsy, even if it is "defined"

See the official spec here for the detailed logical specification.

Syntax

LogicalANDExpression :
BitwiseORExpression
LogicalANDExpression && BitwiseORExpression
LogicalANDExpressionNoIn :
BitwiseORExpressionNoIn
LogicalANDExpressionNoIn && BitwiseORExpressionNoIn
LogicalORExpression :
LogicalANDExpression
LogicalORExpression || LogicalANDExpression
LogicalORExpressionNoIn :
LogicalANDExpressionNoIn
LogicalORExpressionNoIn || LogicalANDExpressionNoIn

Semantics

The production LogicalANDExpression : LogicalANDExpression && BitwiseORExpression is evaluated as follows:
Let lref be the result of evaluating LogicalANDExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is false, return lval.
Let rref be the result of evaluating BitwiseORExpression.
Return GetValue(rref).
The production LogicalORExpression : LogicalORExpression || LogicalANDExpression is evaluated as follows:
Let lref be the result of evaluating LogicalORExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is true, return lval.
Let rref be the result of evaluating LogicalANDExpression.
Return GetValue(rref).
The LogicalANDExpressionNoIn and LogicalORExpressionNoIn productions are evaluated in the same manner as the LogicalANDExpression and LogicalORExpression productions except that the contained LogicalANDExpressionNoIn, BitwiseORExpressionNoIn and LogicalORExpressionNoIn are evaluated instead of the contained LogicalANDExpression, BitwiseORExpression and LogicalORExpression, respectively.
**NOTE** The value produced by a && or || operator is not necessarily of type Boolean. The value produced will always be the value of one of the two operand expressions.
like image 194
Ben McCormick Avatar answered Jan 16 '23 02:01

Ben McCormick