这个 js 表达式安全吗:if( !x || doSomething( x[prop], y[prop] ) === false )

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

根据错误报告,我认为如果 x 为空,以下表达式可能会抛出异常:

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

例外情况是:

Cannot read property 'prop' of null

...好像右边的||即使左侧为真,也会进行评估。 javascript reference 似乎表明这不应该发生,但我不确定。我已经测试过只写 x = null 不会(总是)崩溃,但它在每个 JS 引擎上都能得到保证吗?

编辑:

同样的问题

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

一种说法是:

如果( a && b && c )

... 如果 a === false 则计算 b 或 c?该文档不清楚这种情况,仅针对 "a && ( expr1 && expr2 )",而不是 "a && expr1 && expr2"

完整代码片段

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:为了完整起见,运行 在浏览器中的真实(最小化)代码

  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
      }

Javascript || 运算符短路。如果左侧为 true,则右侧不会计算。这是运算符的基本 属性,应该在所有引擎中平等实施。

因此,右侧只会评估 x 是否为 truthy,并且 Javascript 中的所有 truthy 值都应该是可下标的,不会出错。

话虽如此,y 在此示例中完全未知,可能会引发错误。

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

之前做安全检查。这应该有效

但是注意:

如果您的 prop 属性不存在,这也会 return 出错!

问候

"Is it guaranteed on every JS engine?"

我们实际上无法确定,但标准定义了这些运算符应该如何实现。

逻辑或:

  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

第 3 项没有任何疑问,如果 lref 可以评估为真,则立即返回 lval,并且 rref 永远不会被评估。