Javascript 封装的闭包与类?

Javascript 封装的闭包与类?,javascript,class,closures,Javascript,Class,Closures,我是JS新手(来自C++/etc),我刚刚想到闭包似乎比类更简单、更方便地处理封装。这段代码似乎提供了一种处理封装的简单方法: function addProperty(o) { var value; o["get"] = function() { return value; } o["set"] = function(v) { value = v; } } // create two independent objects which are instances of

我是JS新手(来自C++/etc),我刚刚想到闭包似乎比类更简单、更方便地处理封装。这段代码似乎提供了一种处理封装的简单方法:

function addProperty(o) {
   var value;

   o["get"] = function()  { return value; }
   o["set"] = function(v) { value = v; }
}

// create two independent objects which are instances of pseudo-class 'addProperty',
// which each have their own version of a set of local fields, and methods that
// operate on those fields:
var a = {};
addProperty(a);
var b = {};
addProperty(b);

如果你只想一个类来处理封装(C++中,我发现这是大多数时候),有没有什么好的理由来使用JS类而不是闭包?在我看来,上面的代码比JS类更直观、更紧凑。没有构造器、原型或过度使用“this”。您还可以获得这样的好处:您必须显式声明本地字段,而不是希望您的构造函数中没有任何输入错误

编辑 好的,我就澄清一下。似乎“班级”这个词得到了一些支持。无论如何,对我来说,“类”是类型概念的一个扩展,JS在这方面并不合格,但我可以用我的书(Flanagan)花50页调用类来做各种y类的事情。有点

无论如何,真正的问题是:我在我的第一个web应用程序上使用jQuery选项卡。我昨天注意到这不起作用,因为我的JS代码没有为每个选项卡保留任何私有状态。在选项卡之间切换时,代码的动态/鼠标部分不再正常工作

那么,在应用程序中引入私有状态的最佳方式是什么?大多数代码都是安全的,但处理动态行为的所有内容都需要某种方式来封装每个选项卡的本地状态。在C++背景下,我的一个明显的答案是编写一个定义选项卡的动态部分的类,并在创建选项卡时实例化一个新的“tab”对象。我发现很难弄清楚JS伪类在这里是否有意义,或者我是否应该扩展上面的代码

只要阅读Jonathan的模块模式链接,我现在觉得这可能就是答案


谢谢。

为了封装功能,函数的好处在于您可以使用模块模式:

模块模式提供了创建私有成员和方法的功能,而不需要像ease.js这样的大量开销:


避免闭包的原因是开销

get和set函数的速度比properties慢20倍。闭包的内存开销也很大,与实例数成O(N)

还要注意的是,这些封装的变量没有任何实际好处,它们只是推断性能损失

var AddProperty = {
  constructor: function (v) { this._value = v; return this; },
  get: function () { return this._value; },
  set: function (v) { this._value = v; }
};

var a = Object.create(AddProperty).constructor(1);
var b = Object.create(AddProperty).constructor(2);
我昨天注意到这不起作用,因为我的JS代码没有为每个选项卡保留任何私有状态

你的问题不是没有私有状态,而是你在使用全局状态

简单的解决方案是每个选项卡都有一个对象(如果愿意,也可以有一个“struct”),并在其中存储状态

所以你所要做的就是定义一个标签

var Tab = {
  constructor: function (...) {
    /* init state */
  },
  doTabStuff: function () { /* some method */ },
  ...
}
然后在需要时创建新选项卡

var tab = Object.create(Tab).constructor(...)

这是一个老问题,但有一些问题的答案是失踪的,所以我想我要补充这一点

首先,正如评论者喜欢指出的那样,javascripts中没有任何真正的类,我们只是用闭包来模拟它们。下面是javascript教程所称的“类”:

重要的是,
get
方法只是一个闭包。因此,这与您的代码基本相同。因为闭包必须引用创建它们的环境(这是它们可以使用私有内部状态数据的方式),所以它们的成本比只使用公共函数要高。因此,如果您有一个不需要内部状态的静态方法,则应使用
prototype
关键字将其添加到
Class1

Class1.prototype.staticMethod=function(){...};
这样,静态方法可以在原型链中使用,而不必使用不必要的闭包来消耗额外的内存。您还可以通过在
AddProperty
函数之外添加静态方法来实现这一点


因此,最终,正式javascript“类”与
AddProperty
函数之间的唯一区别在于,当您实际使用类构造函数时,类出现在对象的原型链中,而您的对象只是直接从通用
对象继承。您当然可以编写使用这种区别的代码,但这可能是糟糕的代码。

没有JavaScript类。要么这样,要么我在过去的6年里一直在做错事。它们在代码中可能不被称为类,但出于所有实际目的,您可以声明类并将它们实例到对象中。好的,(a)闭包和(b)闭包的相对优点如何包括原型、构造函数和继承的一组语言构造,在其他语言中,其目的包括封装对象和操作这些对象的方法“,作为JavaScript中的通用封装机制?经典响应:当前
a
b
被分配
未定义
。您可能想在
构造函数中启用链接
@pimvdb我忘记了
返回这个+1-回答得很好。我知道闭包保留了对“stuff”的实时引用,但我不知道它们慢了20倍。@AdamRackis一个函数调用比属性慢了20倍assignment@AdamRackis我认为这就是Java,Java通常喜欢教导人们应该拥有私有状态和getter/setter,即使它与公共状态相同。
Class1.prototype.staticMethod=function(){...};