Is that js expression safe: if( !x || doSomething( x[prop], y[prop] ) === false )

痞子三分冷 提交于 2019-12-24 15:50:31

问题


From a bug report, I think that the following expression might throw an exception if x is null:

if ( !x || doSomething( x[prop], y[prop] ) === false )

The exception is:

Cannot read property 'prop' of null

... as if the right side of the || is evaluated even if the left side is true. The javascript reference seems to indicate that that should not happen, but I'm not sure. I've tested that just writing x = null does not (always) crash, but is it guaranteed on every JS engine ?

EDIT:

Same question about

if( x && foo( x[prop] ) === true && bar() === false )

One way to put it is, does :

if( a && b && c )

... evaluates b or c if a === false ? The doc is not clear about that case, only for "a && ( expr1 && expr2 )", not "a && expr1 && expr2"

Full code snippet

var x = null;
var y = {
  "p1": "p1",
  "p2": "p2"
};

function f() {
  return true;
}

for (var propName in y) {

  if (x && f(y[propName]) === true && f(y[propName]) === false) {
    doSomething(x[propName], y[propName]);
  } else if (!x || f(x[propName], y[propName]) === false) {
    console.log(y[propName]);
  }
}

EDIT2: for completeness, the real (minimized) code that run in the browser

  function a(c, b, e, f) {

        for (var d in b) {
          if (c && _.isObject(b[d]) === true && _.isArray(b[d]) === false) {
            a(c[d], b[d], e, d + ".")
          } else {
            if (!c || _.isEqual(c[d], b[d]) === false) {
              e.push({
                name: f + d,
                value: b[d]
              })
            }
          }
        }
        return e
      }

回答1:


"Is it guaranteed on every JS engine?"

We can't actually know that for sure, but the standard defines, how these operators should be implemented.

Logical OR:

  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).

http://es5.github.io/#x11.11

Item 3 doesn't leave any room to doubts, lval is returned immediately if lref can be evaluated to truthy, and rref will never be evaluated.




回答2:


The Javascript || operator is short-circuiting. The right-hand side will not evaluate if the left-hand side is true. That's a fundamental property of the operator and should be equally implemented across all engines.

Therefore, the right-hand side will only evaluate if x is truthy, and all truthy values in Javascript should be subscriptable without error.

Having said that, y is completely unknown in this example and might throw an error.




回答3:


if (typeof y != 'undefined' && typeof x != 'undefined' && x !== null && y !== null) {
   if (doSomething( x[prop], y[prop] ) === false) {
       //do stuff
   }
}

do the safety check before. this should be working

but note:

if your prop Attribute does not exist, this will return an error too!

greetings



来源:https://stackoverflow.com/questions/34358276/is-that-js-expression-safe-if-x-dosomething-xprop-yprop-false

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!