请参阅http://jsperf.com/in-vs-member-object-access
本质上,为什么检查if ('bar' in foo) {}
明显慢于if (foo.bar !== undefined) {}
?
请参阅http://jsperf.com/in-vs-member-object-access
本质上,为什么检查if ('bar' in foo) {}
明显慢于if (foo.bar !== undefined) {}
?
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) 为真,则返回假。否则,返回真。
你是对的。"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
,但这只是时间问题。和优先事项。