关于 JavaScript 中闭包/封装效率的问题

Posted

技术标签:

【中文标题】关于 JavaScript 中闭包/封装效率的问题【英文标题】:Question about the efficiency of closure/encapsulation in JavaScript 【发布时间】:2011-09-13 23:00:08 【问题描述】:

我对 javascript 有点陌生,如果这是一个愚蠢的问题,请耐心等待。

假设我有一个看起来像这样的“类”:

var obj = function () 
    var val;
    return 
        setVal: function(newVal) 
            val = newVal;
        ,
        getVal: function() 
            return val;
        
    ;
;

假设我的语法是正确的,这定义了一个具有名为“value”的“私有”属性的类,以及设置/获取该属性的方法。现在,我将从这个类创建两个对象:

var myObj = obj();
var yourObj = obj();

这会为 each 对象创建单独的 setVal() 和 getVal() 方法吗?如果不是,为什么不呢?如果是这样,在构建高效的 Web 应用程序时,这是一个严重的问题吗?在大多数/所有情况下,关闭效率的权衡(如果有的话)是否值得?我是笨蛋吗?

谢谢, 杰拉德

【问题讨论】:

这是一篇关于闭包和原型设计的好文章。 ruzee.com/blog/2008/12/… 如果您刚开始使用 javascript,这是一个很好的问题。 【参考方案1】:
var obj = function () 
    var val;
    return 
        setVal: function(newVal) 
            val = newVal;
        ,
        getVal: function() 
            return val;
        
    ;
;

这个函数的作用如下:

创建名为val的变量 创建新对象 创建一个新函数并将其分配给字段setVal 创建一个新函数并将其分配给字段getVal 返回对象。

所以你总是在创造 4 个新事物。

如果页面上的对象少于 1000 个,这不是问题。重构它是一种微优化。

替代方法是不依赖局部变量并使用this._val 表示val 是私有的。

【讨论】:

【参考方案2】:

它确实在概念上这样做。然而,由于这是一种常见的模式,现代 JavaScript JITers 知道如何优化它,以便在内存中只存储一个代码副本,并通过适当的指针重定向使其与相关闭包一起工作。

编辑:虽然我不太愿意深入研究源代码,但这里有一些基本证明。 Download the Chrome dev channel release,并在运行以下代码之前和之后拍摄堆快照:

var obj = /* as above */;

var objs = [];
for (var i = 0; i < 10000; ++i) 
    objs.push(obj());

然后对这段代码做同样的事情:

function Obj()  
Obj.prototype.setVal = function (value)  this._val = value; ;
Obj.prototype.getVal = function ()  return this._val; ;

var objs = [];
for (var i = 0; i < 10000; ++i) 
    objs.push(new Obj());

您会发现堆快照在两种情况下都显示相同的“代码”数字,因此我描述的优化确实正在执行。

【讨论】:

它仍然创建了两个方法实例setValgetVal 是的,在 JavaScript 中确实如此。但是不会降低效率,因为在现代 JIT 编译器所编译到的机器代码级别上,每个都只有一个实例。 请用指向 V8 和 Jaegermonkey 源代码的链接来备份它。我想所有这些函数都有多个实例,每个实例都有指向正确闭包上下文的指针。如果实际上只有两个功能,那么作为优化真的很令人印象深刻 -1 这种优化不仅是不可能的(每个闭包都是一个单独的状态,并且需要保存在内存中的某个地方),而且您可以清楚地看到闭包方法中的javascript内存使用量飙升vs 原型方法。每次调用 +3MB,而每次调用原型几乎没有。

以上是关于关于 JavaScript 中闭包/封装效率的问题的主要内容,如果未能解决你的问题,请参考以下文章

再谈JavaScript闭包及应用

关于Javascript闭包的理解

关于javascript闭包与重构

关于Javascript闭包(Closure)

关于javascript闭包理解

《JavaScript设计模式与开发》笔记 5.关于正确写一个闭包