请考虑以下代码:
var xx=1;
var ff=function(){
return xx+1;
}
ff();
var gg=function(){
return gg.xx+1;
}
gg.xx=1;
gg();
这两种方法之间是否应该有明显的性能差异?在我看来,ff
函数应该执行得更快,因为它只引用一个变量,而gg
函数引用两个变量。我正在开发一款游戏,并希望尽可能地利用各种速度技巧。
答案 0 :(得分:3)
有人问many times before。这里唯一的区别是这两个例子通常都不会被称为闭包,它们是变量和属性解析的简单例子。
以下情况:
var xx = 1;
var ff = function(){
return xx + 1;
}
然后在函数内,首先必须在局部变量对象上解析 xx ,然后在作用域链上解析。所以这至少是两次查找。
以下情况:
var gg = function(){
return gg.xx + 1;
}
gg.xx = 1;
在函数中, gg 必须以与第一种情况完全相同的方式解析(即在局部变量对象上,然后在范围链上),这也是两次查找。找到 gg 后,必须搜索其属性find xx ,这可能涉及多次查找。
鉴于上述情况,假设第一个更快是合乎逻辑的。
当然,这只是一个合乎逻辑的演绎,性能可能实际上与此相反。在某些浏览器中,无论范围链的长度如何,全局变量查找都比本地更快。去图。
可以肯定的是,不同浏览器的性能会有所不同,无论它采用何种方式。这样的性能调整(如果有任何性能优势)正在边缘播放,应该被视为过早优化。
要将其编码为闭包需要类似的内容;
var gg = (function() {
var g;
return function() {
gg = function() {
return g.xx + 1; // Here is the closure
}
if (typeof g == 'undefined') {
g = gg;
}
if (typeof g.xx == 'undefined') {
g.xx = 1;
}
return g();
}
}());
因为 gg 在IIFE完成之前没有值,所以只能在该点创建闭包,只能在函数第一次运行时才能分配值。 / p>
请注意, g 仍然必须在局部变量对象上解析,然后在作用域链上解析,因此仍然需要两次查找并且没有来自闭包的增益(至少没有逻辑增益)。
关于闭包只是要明确:
var xx = 1;
var ff = function(){
return xx + 1;
}
技术上 不形成一个闭包,但不是值得认识的。标识符 xx 在范围链上解析,当某些外部执行上下文完成时,范围链上没有可由 ff 访问的变量。所以闭包只存在于函数所用的时间,因此并不比词法范围更显着。
相反:
var ff = (function() {
var closureVariable;
// This "inner" function has a closure with closureVariable
// If value is undefined, get (return) the value. Otherwise, set it
return function(value) {
if (typeof value == 'undefined') {
return closureVariable;
}
closureVariable = value;
};
}());
在这种情况下, ff 可以独占访问 closureVariable ,这是一个在创建它的函数完成后仍然可以访问的变量:
// set the value
ff('foo');
// get the value
console.log(ff()); // foo
closureVariable 只能由 ff 访问(与全局变量不同),并且会持续多次调用(与局部变量不同)。闭包的这个特性允许它们emulate private members。
另一个特性是许多函数可以对同一个变量进行闭包(或priveliged访问),从而模拟一种继承。