闭包与类的封装? [英] Closures vs. classes for encapsulation?

查看:103
本文介绍了闭包与类的封装?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是JS的新手(从C ++ / etc),它只是发生在我看来,闭包似乎是一个更简单和更方便的方式来处理封装比类。这个代码似乎给了一个简单的处理封装的方法:

  function addProperty(o){
var value;

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

//创建两个独立的对象,它们是伪类'addProperty',
//的实例,每个对象都有自己版本的一组局部字段,和
//对这些字段操作的方法:
var a = {};
addProperty(a);
var b = {};
addProperty(b);

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



EDIT



好吧,我会澄清。看起来像'类'字得到一些支持。一个类,对我来说,是类型概念的扩展,JS不符合前面,但我可以做各种类-Y事情与我的书(Flanagan)花费50页调用类。排序。



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



那么,什么是最好的方式来引入私人状态的应用程序?大多数代码是安全的,但处理动态行为的一切都需要一些方法来封装每个选项卡的本地状态。有了C ++的背景,对我来说明显的答案是写一个类来定义一个tab的动态部分,并且每次创建一个tab时实例化一个新的tab对象。我发现很难弄清楚JS伪类是否真的在这里有任何意义,还是我应该扩展上面的代码。



只读模块模式链接从乔纳森,现在在我看来,这可能是答案。



感谢。

解决方案

避免关闭的原因是开销。



你的get和set函数比属性慢了20倍。你的闭包也有很大的内存开销,O(N)和实例数。



还要注意,这些封装的变量没有真正的好处,惩罚。

  var AddProperty = {
constructor:function(v){this._value = v;返回这个; },
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(...)
pre>

I'm new to JS (from C++/etc), and it's just occurred to me that closures seem to be a simpler and more convenient way to handle encapsulation than classes. This code seems to give a simple way to handle encapsulation:

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);

If you just want a class to handle encapsulation (in C++, I find this is most of the time), is there any good reason to use a JS class instead of a closure? The code above seems to me to be more intuitive and compact than JS classes. No constructors, prototypes, or excessive use of 'this'. You also get the benefit that you must explicitly declare local fields, instead of hoping that you don't make any typos in your constructor.

EDIT

Ok, I'll just clarify. Seems like the 'class' word gets some backs up. A "class", to me anyway, is an extension of the type concept, and JS doesn't qualify on that front, but I can do various class-y things with what my book (Flanagan) spends 50 pages calling classes. Sort of.

Anyway, the real question is this: I'm using jQuery tabs on my first web app. I noticed yesterday that this doesn't work, because my JS code doesn't keep any private state for each tab. When I swap between tabs, the dynamic/mouse parts of my code no longer work properly.

So, what's the best way to introduce private state into the app? Most of the code is safe, but everything that handles dynamic behaviour needs some way to encapsulate per-tab local state. With a C++ background, the obvious answer to me is to write a class that defines the dynamic parts of a tab, and to instantiate a new 'tab' object each time a tab is created. What I'm finding it difficult to get my head around is whether JS pseudo-classes actually make any sense here, or whether I should extend the code above.

Just read the module patterns link from Jonathan, and it now seems to me to be that that may be the answer.

Thanks.

解决方案

The reasons to avoid closures is overhead.

Your get and set functions are trivially 20x slower than properties. Your closures also have a large memory overhead that is O(N) with the number of instances.

Also note that these encapsulated variables have zero real benefit, they just infer performance penalties.

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);

I noticed yesterday that this doesn't work, because my JS code doesn't keep any private state for each tab.

Your problem is not that you don't have private state, it's that you're using global state.

The easy solution is to have an object per tab (or a "struct" if you prefer) and store state in it.

So all you have to do is define a tab

var Tab = {
  constructor: function (...) {
    /* init state */
  },
  doTabStuff: function () { /* some method */ },
  ...
}

And then create new tabs when you need them

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

这篇关于闭包与类的封装?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆