Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript原型和实例创建_Javascript_Prototype - Fatal编程技术网

Javascript原型和实例创建

Javascript原型和实例创建,javascript,prototype,Javascript,Prototype,我很抱歉,因为这个话题经常出现,但我今天读到的任何东西都没有充分解释这个问题 我试图创建一个简单的集合类(同时学习javascript原型),用于存储具有“name”属性的对象,并允许通过索引或值访问其成员。到目前为止,我得到了这个: function Collection() {} Collection.prototype.constructor = Collection; Collection.prototype._innerList = []; Collection.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];
    }
};

问题是:

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

基本上,新实例
bar
是使用所有属性创建的,这些属性具有
foo
中数据的当前值。我知道我可以通过在构造器中放置外部参照等来解决这个问题,但我试图理解原型是如何工作的。如果我创建了一个新实例,并对该实例中的数据进行了更改,为什么在我创建另一个新实例时这些值会保留下来


如果我从
foo
bar
的原型对属性进行进一步更改,它们是独立的,因此我似乎不会以某种方式引用任何东西的相同实例。那么是什么导致
bar
被实例化为
foo
中的当前值呢?

考虑一下满教室的学生。在原型上放一些东西就像在白板上放一些东西让他们都能看到。当你宣布

Collection.prototype._innerList = [];
你给了每一个收藏品那财产;无论调用
newcollection()
如何,对白板的任何更改都会影响所有学生。但是,如果在构造函数中定义它,或将其中一个函数定义为
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

编辑
与你的问题不太相关,但这是我做的事,所以我会把它扔出去。每当我在原型上做某件事时,如果我没有返回某件事,我就会返回
this
。它允许链接,因此您可以执行
instance.function1().function2().function3()
,只要
function1
function2
返回
这个

您就可以将原型看作是为该类的所有对象提供共享变量。就像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>");
函数集合()
{
这个。_innerList=[];
这个.\u xref={};
}
Collection.prototype.count=函数(){返回此值。_innerList.length;};
Collection.prototype.add=函数(obj){
this._xref[obj.name]=this._innerList.push(obj)-1;
}
Collection.prototype.get=函数(id){
如果(id的类型==“字符串”){
返回此。_innerList[this._xref[id];
}否则{
返回此项。_innerList[id];
}
};
var foo=新集合();
add({name:“someitem”,value:“hello world”});//foo.count()==1
document.write(foo.count(),“
”; var bar=新集合(); 添加({name:“someotheritem”,value:“helloworld”});//酒吧 document.write(bar.count(),“
”;
基本上,如果你在原型中使用一个字段,它的功能就像一个静态字段?是的,原型中的任何内容只在内存中存在一次。太好了,谢谢。有道理。有这么多的东西写在那里,但没有一本是面向像我这样的人的,他们似乎无法停止以传统的OO继承方式思考问题。你能解释一下第一点吗?这是否只允许您创建一个新实例而不使用单词
new
?是的,如果您忘记了新实例,这只是一个陷阱。使用新的更好,但我出于习惯而将其包括在内。谢谢,这也是一个很好的解释。另一个人先来了,但我给了你一张赞成票。永远是伴娘,永远不是新娘:-)谢谢你的支持。我想这是一个更好的答案。与静力学的比较清楚地表明了这一点。