"return doc && doc.userId === userId;" return 不应该是假的吗?

Shouldn't "return doc && doc.userId === userId;" return false?

我正在关注 Discover Meteor tutorial,在提交 8-1 之后我们添加:

// Check that the userId specified owns the documents
ownsDocument = function(userId, doc) {
  return doc && doc.userId === userId;
}

我不明白的是 doc 和 userId 不是严格相等的 (===),为什么这样行得通?

供参考:

文档:

{ _id:       '1a2b3c4d',
  url:       'blahblah.com',
  title:     'blah blah',
  userId:    '0w9x8y7z',
  author:    'testuser',
  submitted: '...'}

doc.userId:

userId: 0w9x8y7z

用户 ID:

userId: 0w9x8y7z

我明白 doc.userId === userId,但为什么 doc && doc.userId === userId 会通过?

这是 JavaScript 中常用的惯用语,如果您想在访问其属性之一之前检查对象不是 undefined(或其他 falsey),您可以说:

obj && obj.prop

如果第一个参数为假,&& operator 不会计算第二个参数,因此这可以保护您的代码不会尝试从值为未定义的变量中检索 属性 值[=16] =]

因此,您示例中的 return 语句等同于:

if (doc){
    return doc.userId;
} else {
    return doc;
}

如果检查 Operator Precedence table,您会发现相等 (== / ===) 的优先级高于 AND (&&),因此:

doc && doc.userId === userId

是这样解析的:

doc && (doc.userId === userId)

而不是这个:

(doc && doc.userId) === userId

然后,由于 doc 为真,引擎会评估 doc.userId === userId 和 returns 结果。

您困惑的根源似乎是您对此的解释:

if(doc && doc.userId === userId)

作为"if both doc and doc.userId are equal to userId"。事实并非如此。

&& 的每一边都是一个单独的条件。等同于:

if(doc == true && doc.userId === userId)

其次,左侧的 == true 部分是多余的,因此在检查变量是否为 truthy.

时通常不包括在内

进行 truthy 检查的原因是您要在尝试访问 [=35] 之前检查 doc 是否 falsey =] 就可以了。使用逻辑 AND,如果左侧的计算结果不为真,则不会执行右侧。如果不进行检查,如果 docfalsey 那么将在尝试访问 none 对象上的 属性 时产生错误。