13

请参阅http://jsperf.com/in-vs-member-object-access

本质上,为什么检查if ('bar' in foo) {}明显慢于if (foo.bar !== undefined) {}

4

2 回答 2

5

foo.bar !== undefined仅检查这两个值以查看它们是否匹配。

While'bar' in foo将不得不使用某种机制来循环遍历 的属性foo以查看是否bar在其中。

这是来自 Ecma-script 的有趣读物

in 运算符

产生式 RelationalExpression : RelationalExpression 在 ShiftExpression 中的评估如下:
1. 评估 RelationalExpression。
2. 调用 GetValue(Result(1))。
3. 评估 ShiftExpression。
4. 调用 GetValue(Result(3))。
5. 如果 Result(4) 不是对象,则抛出 TypeError 异常。
6. 调用 ToString(Result(2))。
7. 使用参数Result(6)调用Result(4)的[[HasProperty]]方法。
8. 返回结果(7)。

严格不等于运算符 ( !== )

产生式 EqualityExpression : EqualityExpression !== RelationalExpression 评估如下:
1. 评估 EqualityExpression。
2. 调用 GetValue(Result(1))。
3. 评估关系表达式。
4. 调用 GetValue(Result(3))。
5. 执行比较 Result(4) === Result(2)。(见下文。)
6. 如果 Result(5) 为真,则返回假。否则,返回真。

于 2012-12-13T18:57:45.997 回答
4

你是对的。"bar" in foo比 慢是没有意义的foo.bar

唯一的原因是它没有像更常见的语法in那样受到 JIT 工程师的关注。foo.bar

特别是在您的 jsperf 测试中,该属性确实作为其foo自身的直接属性(不是原型)存在,因此按理说它'bar' in foo不应该比foo.bar !== undefined. 如果有的话,它应该更快。两者的主要区别在于,in甚至不用检查属性值就可以回答!

在这种foo.bar情况下,我希望 V8 引擎和 SpiderMonkey 引擎都会检测到代码没有做任何有用的事情(也就是说,它没有可观察到的效果)并完全优化它。基准没有衡量任何实际工作。

显然引擎还不够聪明,无法优化"bar" in foo,但这只是时间问题。和优先事项。

于 2014-08-08T20:13:01.720 回答