Javascript 访问闭包变量与对象变量的速度
考虑以下代码:Javascript 访问闭包变量与对象变量的速度,javascript,closures,Javascript,Closures,考虑以下代码: var xx=1; var ff=function(){ return xx+1; } ff(); var gg=function(){ return gg.xx+1; } gg.xx=1; gg(); 这两种方法之间是否存在明显的性能差异?在我看来,ff函数应该执行得更快,因为它只引用一个变量,而gg函数引用两个变量。我正在开发一款游戏,希望尽我所能利用所有可能的速度技巧。有人问我这个问题。这里唯一的区别是,这两个示例通常都不是闭包,它们是变量和属性解析的简
var xx=1;
var ff=function(){
return xx+1;
}
ff();
var gg=function(){
return gg.xx+1;
}
gg.xx=1;
gg();
这两种方法之间是否存在明显的性能差异?在我看来,
ff
函数应该执行得更快,因为它只引用一个变量,而gg
函数引用两个变量。我正在开发一款游戏,希望尽我所能利用所有可能的速度技巧。有人问我这个问题。这里唯一的区别是,这两个示例通常都不是闭包,它们是变量和属性解析的简单示例
在下列情况下:
var xx = 1;
var ff = function(){
return xx + 1;
}
var gg = function(){
return gg.xx + 1;
}
gg.xx = 1;
然后在函数中,必须首先在局部变量对象上解析xx,然后在作用域链上解析xx。所以至少有两次查找
在下列情况下:
var xx = 1;
var ff = function(){
return xx + 1;
}
var gg = function(){
return gg.xx + 1;
}
gg.xx = 1;
在函数中,必须以与第一种情况完全相同的方式解析gg(即在局部变量对象上,然后在范围链上),这也是两种查找。找到gg后,必须搜索其属性以查找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结束之前没有值,因此只能在该点创建闭包,因此只能在以后首次运行函数时分配该值
请注意,g仍然必须在局部变量对象上解析,然后在范围链上解析,因此仍然有两个查找,并且闭包没有收益(至少没有逻辑收益)
编辑2
只是想澄清一下关于关闭的问题:
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访问(与全局变量不同),并在多次调用中保持不变(与局部变量不同)。正是闭包的这一特性使它们能够
另一个特点是,许多函数可以对同一变量进行闭包(或私有访问),模拟一种继承。有人问过这一点。这里唯一的区别是,这两个示例通常都不是闭包,它们是变量和属性解析的简单示例 在下列情况下:
var xx = 1;
var ff = function(){
return xx + 1;
}
var gg = function(){
return gg.xx + 1;
}
gg.xx = 1;
然后在函数中,必须首先在局部变量对象上解析xx,然后在作用域链上解析xx。所以至少有两次查找
在下列情况下:
var xx = 1;
var ff = function(){
return xx + 1;
}
var gg = function(){
return gg.xx + 1;
}
gg.xx = 1;
在函数中,必须以与第一种情况完全相同的方式解析gg(即在局部变量对象上,然后在范围链上),这也是两种查找。找到gg后,必须搜索其属性以查找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结束之前没有值,因此只能在该点创建闭包,因此只能在以后首次运行函数时分配该值
请注意,g仍然必须在局部变量对象上解析,然后在范围链上解析,因此仍然有两个查找,并且闭包没有收益(至少没有逻辑收益)
编辑2
只是想澄清一下关于关闭的问题:
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访问(与全局变量不同),并在多次调用中保持不变(与局部变量不同)。正是闭包的这一特性使它们能够
另一个特点是,许多函数可以对同一变量进行闭包(或特权访问),模拟一种继承。没有闭包,变量解析(xx和gg)是相同的。第二种方法还涉及到属性查找,因此速度应该较慢,但没有考虑浏览器的异常情况。更担心的是保持数据井然有序。与其他方面相比,这方面的性能差异将是极其微小的-例如驱动DOM。没有闭包,变量分辨率(xx和gg)是相同的。第二种方法还涉及到属性查找,因此速度应该较慢,但没有考虑浏览器的异常情况