简体   繁体   中英

Logical OR (||) in JavaScript

A book states following rules for OR:

  • If the first operand is an object, then the first operand is returned.
  • If the first operand evaluates to false, then the second operand is returned.
  • If both operands are objects, then the first operand is returned.
  • If both operands are null, then null is returned.
  • If both operands are NaN, then NaN is returned.
  • If both operands are undefined, then undefined is returned.

However I observed following behavior while coding:

        var result18 = (NaNVar || undefinedVar);  //undefined
        var result19 = (NaNVar || nullVar);  //null
        var result20 = (undefinedVar || NaNVar);  //NaN
        var result21 = (undefinedVar || nullVar); //null
        var result22 = (nullVar || NaNVar); //NaN
        var result23 = (nullVar || undefined);   //undefined

How can I justify this behavior for those rules?

This rule is the key:

If the first operand evaluates to false, then the second operand is returned.

All of your left hand side values evaluate to false, so the right hand side is returned.

Here's a good definition from MDN if it helps you:

expr1 || expr2

Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true; if both are false, returns false.

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/Logical_Operators

Sorry for the confusion around the description in the book. I was trying to enumerate edge cases and I see how that could cause some confusion.

You can accurately describe the operation using only two rules: if the first argument is truthy then return the first argument; if the first argument is falsy return the second argument. Your third rule doesn't just apply to this operator, an undeclared variable will always causing her to be thrown when you try to use it. It doesn't matter what you try to use it for (with the exception of typeof and delete, which work fine in undeclared variables).

Your book has chosen a terrible way to describe the logical OR operator.

For example, this rule is far too limiting.

If the first operand is an object, then the first operand is returned.

The operator does not do any sort of type check. It doesn't care if the first or second operand is an "object". It only cares about how they coerce to a boolean.

Take this example.

"foobar" || false

The first operand is a string, not an object, but it will coerce to the boolean true , so the first operand is returned.

Boolean("foobar"); // true

Your book is walking through bullet points as though it was following some sort of specified algorithm. There is no such algorithm. The comparison is strictly based on Boolean coercion.

To put it simply,

  • it evaluates operands from left to right until one is found that will coerce to true or until it runs out of operands.
  • the last operand evaluated is returned (uncoerced)

11.11 Binary Logical Operators

  1. Let lref be the result of evaluating LogicalORExpression.

  2. Let lval be GetValue(lref) .

  3. If ToBoolean(lval) is true , return lval .

  4. Let rref be the result of evaluating LogicalANDExpression.

  5. Return GetValue(rref) .

Yes after observing the results, I concluded two simple rules:

        //1: if the first operand evaluates to true then it is returned (here it means actual //value of operand is returned but not the evaluated value that is true)
        //following values evaluates to ture: non-empty string, non-zero number and //none of these values- NaN, null, undefined

        var result = ("Mahesh" || false) //"Mahesh"
        var result = ("Mahesh" || true) //"Mahesh"
        var result = ("Mahesh" || undefined) //"Mahesh"
        var result = ("Mahesh" || null) //"Mahesh"
        var result = ("Mahesh" || NaN) //"Mahesh"
        var result = (5 || false) //5
        var result = (5 || true) //5
        var result = (5 || null) //5
        var result = (5 || NaN) //5
        var result = (5 || undefined) //5

        //2: if first operand evaluates to false then the value of second operand is //returned, again without evaluating it
        //following values evaluate to false: empty string (""), number zero (0),  null, //NaN, undefined or false)

        var result = (false || NaN);  //NaN
        var result = (false || null);  //null
        var result = (false || undefined);  //undefined
        var result = (false || "Mahesh");  //Mahesh
        var result = (false || 5);  //5

        var result = (NaN || false);   //false
        var result = (NaN || true);   //true
        var result = (NaN || NaN);   //NaN
        var result = (NaN || null);  //null
        var result = (NaN || undefined);  //undefined
        var result = (NaN || "Mahesh");   //Mahesh
        var result = (NaN || 5);   //5

        var result = (null || false);  //false
        var result = (null || true);  //true
        var result = (null || NaN); //NaN
        var result = (null || null);  //null
        var result = (null || undefined);   //undefined
        var result = (null || "Mahesh");  //Mahesh
        var result = (null || 5);  //5

        var result = (undefined || false);  //false    
        var result = (undefined || true);  //true
        var result = (undefined || NaN);  //NaN
        var result = (undefined || null); //null
        var result = (undefined || undefined);  //undefined
        var result = (undefined || "Mahesh");  //Mahesh
        var result = (undefined || 5);  //5

        var result = (0 || false); //false
        var result = (0 || true); //true
        var result = (0 || NaN); //NaN
        var result = (0 || null);  //null
        var result = (0 || undefined);   //undefined
        var result = (0 || "Mahesh"); //Mahesh
        var result = (0 || 5); //5

        var result = ("" || false); //false
        var result = ("" || true); //true
        var result = ("" || NaN); //NaN
        var result = (""|| null);  //null
        var result = (""|| undefined);   //undefined
        var result = ("" || "Mahesh"); //Mahesh
        var result = ("" || 5); //5

        //Note: if the first operand evaluates to false and if the second operand is undeclared 
        //variable then it will cause an error
        var result = (false || undeclaredVar);    //error

I think that's all in it in simpler words. Can anyone here confirm if I have got right understanding? I tried this in IE10, hope things will be consistent across other browsers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM