Javascript原型和实例创建

Jam*_*rgy 13 javascript prototype

我道歉,因为这个话题出现了很多,但我还没有能够在今天读到的任何内容中充分解释这个问题.

我正在尝试创建一个简单的集合类(并同时学习javascript原型),用于存储具有"name"属性的对象,并允许其成员通过索引或值访问.到目前为止,我有这个:

function Collection() {}
Collection.prototype.constructor = Collection;
Collection.prototype._innerList = [];
Collection.prototype._xref = {};
Collection.prototype.count = function () { return this._innerList.length; };
Collection.prototype.add = function (obj) {
    this._xref[obj.name] = this._innerList.push(obj) - 1;
}
Collection.prototype.get = function (id) {
    if (typeof id == "string") {
        return this._innerList[this._xref[id]];
    } else {
        return this._innerList[id];
    }
};
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/YrVFZ/

问题:

var foo = new Collection();
foo.add({name: "someitem", value:"hello world"});   // foo.count()== 1

var bar= new Collection();
bar.add({name: "someotheritem", value:"hello world"}); // bar.count()== 2
Run Code Online (Sandbox Code Playgroud)

嗯...

基本上,bar创建新实例的所有属性都包含数据的当前值foo.我知道我可以通过在构造函数中放置_xref等来解决这个问题,但我正在尝试理解原型如何工作.如果我创建一个新实例,并对该实例中的数据进行更改,那么当我创建另一个新实例时,为什么这些值会继续?

如果我从原型中对属性进行进一步的更改,foo或者bar它们是独立的,那么看起来我似乎并不是在某种程度上引用同一个实例.那么是什么导致bar用当前值实例化foo

Rob*_*ert 22

考虑一个满是学生的教室.把东西放在原型上就像把东西放在白板上让所有人看到.当你宣布时

Collection.prototype._innerList = [];
Run Code Online (Sandbox Code Playgroud)

你给每个收藏品都是属性的; 无论是否呼叫new Collection()白板的任何变化都会影响所有学生.但是,如果您在构造函数或其中一个函数中定义它this.variableName = [],则每个副本都有自己的variableName,就像给每个学生分发一份讲义一样.显然,在某些情况下,可以在白板上放置一些东西,例如从学生到学生的通用说明,但如果每个学生的每个项目都不同,那么它应该是个人财产.希望这个解释有意义......

你想这样做.

function Collection() {
    if (!this instanceof Collection)
        return new Collection();
    this._innerList = [];
    this._xref = {};

    return this;
}

Collection.prototype.count = function() {
    return this._innerList.length;
};
Collection.prototype.add = function(obj) {
    this._xref[obj.name] = this._innerList.push(obj) - 1;
}
Collection.prototype.get = function(id) {
    if (typeof id == "string") {
        return this._innerList[this._xref[id]];
    } else {
        return this._innerList[id];
    }
};

var foo = new Collection();
foo.add({name: "someitem", value:"hello world"});   
console.log(foo.count()); // 1

var bar= new Collection();
bar.add({name: "someotheritem", value:"hello world"});
console.log(bar.count()); // 1
Run Code Online (Sandbox Code Playgroud)

http://jsfiddle.net/vXbLL/

编辑

与你的问题不太相关,但这是我做的事情,所以我会把它扔出去.每当我在原型上做某事时,如果我没有回复某些东西,我会回来this.它允许链接,所以你可以做instance.function1().function2().function3(),只要function1function2返回this.

  • 所以基本上,如果你在原型中使用一个字段,它的功能就像一个静态字段? (2认同)

Bri*_*ein 5

您可以将原型视为给出该类共享变量的所有对象.就像c ++类中的静态变量一样,如果有意义的话.这对于函数来说是可以的,因为它们对于类的每个实例都是相同的.但是,如果您希望对象具有自己的非共享变量,则不应使用原型.一种简单的方法是在构造函数方法中分配它们,如下所示:

function Collection() 
{
this._innerList = [];
this._xref = {};
}

Collection.prototype.count = function () { return this._innerList.length; };
Collection.prototype.add = function (obj) {
    this._xref[obj.name] = this._innerList.push(obj) - 1;
}
Collection.prototype.get = function (id) {
    if (typeof id == "string") {
        return this._innerList[this._xref[id]];
    } else {
        return this._innerList[id];
    }
};

var foo = new Collection();
foo.add({name: "someitem", value:"hello world"});   // foo.count()== 1
document.write(foo.count(),"<br>");

var bar= new Collection();
bar.add({name: "someotheritem", value:"hello world"}); // bar.cou
document.write(bar.count(),"<br>");
Run Code Online (Sandbox Code Playgroud)