var completeObj = {a: { b: { c: { d: { e: { f: 23 } } } } } };
var funcA = function(obj){
var a = 'a',b='b',c='c',d='d',e='e',f='f';
return obj[a][b][c][d][e][f];
}
var funcB = function(obj){
return obj['a']['b']['c']['d']['e']['f'];
}
funcA比funcB慢得多,寻找范围成本变化这么多时间? 测试网址:http://jsperf.com/static-and-dynamic-argument THX
答案 0 :(得分:2)
http://jsperf.com/static-and-dynamic-argument/2
我拿了你的测试用例并添加了一个“证明一点”。当您通过['key']
表示法访问对象中的某些内容时,您执行的操作与通过.key
访问该内容相同。编译器非常聪明,知道['a']
等同于.a
。但是,当你在其中粘贴变量时,正如Bergi在他的评论中提到的那样,编译器不知道[a]
实际上是['a']
。
答案 1 :(得分:1)
这是因为局部变量(函数范围)成为内部Variable
对象的属性。因此,对obj[a][b][c][d][e][f]
的调用最终会先访问a
对象上的f
,然后再访问Variable
。
答案 2 :(得分:1)
它与变量或变量范围无关(纯局部变量实际上是免费的),但使用反射来访问属性而不是常量。
obj['a']['b']['c']['d']['e']['f'];
等于obj.a.b.c.d.e.f
所以即使从源代码知道将访问哪些属性也是如此。
但是,对变量使用括号表示法需要在运行时确定将访问哪些属性,因此它们完全不同。在Java中,以前的代码就像使用Reflection库来访问属性,而后者与使用普通的静态点访问相同。
那么为什么编译器“不会意识到”变量也是静态的呢?那么你的代码是完全不合理的,JIT浪费时间优化不合理的代码是一个糟糕的JIT。
为什么它会意识到['a']
与.a
相同?至少根据我的经验,让解析器为点和括号访问吐出相同的MemberAccess对象然后检查表达式是否为常量字符串要简单得多。