如何在JavaScript中允许多个实例,如果对象被包装在匿名函数中

3
作为Crockford和John Resig所倡导的做法,一个对象应该被包裹在匿名函数内。但是如果需要多个实例怎么办?当它被包裹时,只会存在一个实例(单例)。
更新:我忘记说了,我当然是在谈论框架的根对象(不是jQuery而是我的自己的框架),而不是任何对象。由于它是一个框架,实例的数量是未知的,并且由客户端决定。
我猜99.99%的人只使用框架而不构建自己的框架,因此,如果你不知道,请不要试图回答你自己不理解的问题 :)

你能提供一个例子吗? - Felix Kling
我认为这里有一个答案:https://dev59.com/yW025IYBdhLWcg3wwYz4 - user310291
你是在谈论像jQuery的多个实例这样的东西吗? - vol7ron
是的,除非它不是针对Jquery,而是针对我的自己的框架库。 - user310291
是的,我理解了,这就是“something like”所暗示的意思。 - vol7ron
4个回答

6
这是一种从直接实例化的函数中创建伪命名空间的简单示例(还有其他方式),如下所示:

var NS = (function(){
   function Person(name,gender,age){
     this.name = name || '';
     this.gender = gender || '';
     this.age = age || 0;
   }

   return {
     createPerson: function(n,g,a) {return new Person(n,g,a);}
   };

}());

现在,NS是一个伪命名空间,您可以使用它来创建一个Person实例,就像这样:
var pete = NS.createPerson('Pete','male',23);
alert(pete.name); //=> Pete

NS函数中,您可以使用函数、对象、本地变量等创建完整的框架。在返回的对象中,您可以包含所有必要的公共方法,以使其正常运行。


2
你是否在寻找类似这样的东西?
var autos = {

    Car: function (id, model) {
        this.id = id;
        this.model = model;
        this.isMoving = false;

        this.drive = function drive() {
            this.isMoving = true;
        };

        this.stop = function stop() {
            this.isMoving = false;
        };
    }

};

使用方法:

var car = new autos.Car(123, 'MDX');
car.drive();
car.stop();

autos没有被匿名函数包装。当被包装时,你不能创建新的对象,这就是我的观点 :) - user310291
根据你所说的一切,似乎你正在尝试在全局空间内访问闭包的作用域,这是设计上永远不会起作用的。匿名函数的整个意义就在于将其与全局空间分开。 - vol7ron
你到底怎么指望去实例化一个匿名对象?这根本没有任何意义。我错过了什么吗? - Kon

1

2011-06-26 (1:26P EST) 你可能正在寻找你的框架的深层副本


由于您没有提供示例,这里提供一个使用jQuery的示例。对于每个新的“实例”,您都可以向框架添加一个属性,该属性将保存它。或者,您可以只使用框架数组,并将您的实例推入堆栈中。无论哪种方式,它都将是一个变量来容纳多个实例/副本。

var frameworks = {};
frameworks.a = jQuery.extend(true, {}, jQuery);
frameworks.b = jQuery.extend(true, {}, jQuery);


(function($){$.fn.foo = function(arg){var foo=arg;}})(frameworks.a);
console.log(frameworks.a.fn.foo.toString());                  // uses 'arg'

(function($){$.fn.foo = function(bar){var foo=bar;}})(frameworks.b);
console.log((frameworks.a).fn.foo.toString());                // still uses 'arg'


原始答案


这是你想要的吗?

var frameworks = {};
frameworks.base = function(i){var foo = i; return foo;};
frameworks.a = (frameworks.base)('a');
frameworks.b = (frameworks.base)('b');

document.write(frameworks.a);
document.write(frameworks.b);

作者的评论: 我猜99.99%的人只使用框架,不自己构建,所以如果您不知道,请不要试图回答您自己不理解的问题 :)

回复: 我猜99.99%的自己构建的人没有遇到这样的情况,因为他们了解框架的目的,以及如果需要一个实例,说明设计存在缺陷。此外,如果有人如此“精通”设计一个尚不存在于互联网上的框架,那么他们应该能够理解如何实现自己的“实例”,而不会使全局名称空间混乱。


真的吗?那你没有读约翰·雷西格(John Resig)的文章,他在谈论多个实例。 - user310291
你没有将你的框架包装在匿名函数中,这正是我在问题中想要表达的关键点。 - user310291
不,框架变量是一个保存各种框架实例(例如a、b)的变量。您需要某种方式在全局范围内调用这些框架,就像使用$jQuery来调用该框架一样。当涉及到John Resig时,他并不是JavaScript的全部和终极,毕竟他来自波士顿。 - vol7ron

1

正如Crockford和John Resig所提倡的那样,应该在匿名函数中包装对象。

是的,特别是为了避免将对象泄漏到全局空间中...但我不认为他们建议在使用对象时每个地方都这样做。

如果您想要在全局空间中有多个对象,您会如何命名它们?CarOne和CarTwo吗?

那么,您可以使用一个名为MyGarage的单个全局变量,MyGarage可以包含CarOne和CarTwo,这样怎么样?


好的,我忘了说,当然是指框架的根对象,而不是任何对象。 - user310291
由于它是一个框架,实例的数量是未知的,并且由客户决定。 - user310291
你一直在提到框架(framework)这个术语,然后又使用实例(instances)。你需要一个更好的例子。 - vol7ron
一个框架是通过一个根对象来实现的,那为什么你要对比这两者呢? - user310291
1
我进行对比是因为框架不应该需要一个实例;实例应该在框架内部。按设计,框架是一种旨在辅助实例的工具,如果有多个实例,那么你只会使用不必要的资源。再次强调,如果您具有与此想法相反的某种奇怪情况(我并不是说您没有),则需要展示更好的例子。 - vol7ron
非常同意vol7ron的看法(嗯,你确实需要一个实例……但就这些)。 - Steve

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接