我不确定如何标题,但这里有一个例子让我惹恼了我
myLib.prototype._handlers = {};
myLib.prototype.destroy = function () {
this._handlers = {};
}
我正在写测试,幸运的是它抓住了这个问题。破坏方法实际上并不起作用。
为什么会这样?我认为原型上的属性是为每个new myLib
实例创建的,但是通过编写这些测试所有 new myLib
实例都有这些处理程序。
答案 0 :(得分:5)
您可以在原型上设置非功能。问题是原型上的属性是在对象的所有实例之间共享的。这通常不是您想要的数据属性,但它是您想要的函数属性。
因此,相反,您通常会在对象的构造函数中初始化数据属性,这使得它们自己拥有"每个实例都有唯一的属性,通常是你想要的。
我认为原型上的属性是为每个创建的 新的myLib实例,但从编写这些测试所有新的myLib 实例有这些处理程序。
原型是一个对象,用作属性的查找机制。当您引用var x = obj.prop
时,Javascript首先查看obj
对象本身,以查看是否存在名为"prop"
的属性。如果有,那被认为是"拥有"属性和它的值被提取。如果没有,那么它转到原型对象,看它是否有一个"拥有"名为"prop"
的属性。如果是,则返回该值。如果它没有那个命名属性,那么它会检查原型对象是否有自己的原型,如果有,它会检查一个,依此类推......
因此,原型充当查找参考。没有复制或创建任何新内容。这只是一个"参考"到可用于查找的原型。这就是原型在所有实例之间共享的原因。出于多种原因,它是故意设计的。一个原因是它的存储效率很高。所有实例共享的原型对象只有一个,因此所有这些引用都不必在每个对象实例上重复。
使用以下内容分配属性时
obj.someProp = "foo";
它只会影响"拥有"属性。它不会影响原型。如果有一个"拥有"在名为"someProp"
的对象上的属性,然后更新它的值。如果没有,那么一个新的"拥有"在实际对象实例上创建属性。如果原型上有这个名称的属性,那么该值现在基本上是隐藏的,因为Javascript属性查找方案将找到" own"属性优先,并将从那时起使用(只要它存在)。
了解在.destroy()
方法中分配属性时可能也很重要,例如:
myLib.prototype._handlers = {};
myLib.prototype.destroy = function () {
this._handlers = {};
}
执行myLib.prototype._handlers
方法时,实际上并没有触及obj.destroy()
值。相反,this._handlers = {};
在对象的实际实例上创建一个新属性,一个"拥有"属性。对this._handlers
的任何引用都会找到"拥有"首先是财产,从那时起将会使用什么,所以它可能会出现#34;喜欢它改变了原型价值,但新的"拥有"属性只是掩盖了原型值。
答案 1 :(得分:1)
我认为原型上的属性是为每个新的myLib实例创建的新属性
没有。原型不会创建任何东西。原型继承是一种级联查找系统,其中对象上的属性的查找可以升级为原型祖先。
每个对象都有继承的属性及其“自己的”属性。实际上只有“自己的”属性直接存在。原型值不直接存在于实例上,而是当您在对象上请求某个属性名称时访问它们,并且该属性不作为自己的属性存在。
设置属性值始终直接在对象上设置自己的属性。因此,this._handlers = {}
直接在您调用_handlers
方法的实例上设置(并可能创建)destroy
属性。虽然属性 access 会对原型链进行级联以查找具有正确名称的属性,但设置属性不这样做。
理解this
值在函数调用时动态设置也很重要,并且可能因调用而异。也就是说,即使instance1.destroy()
函数与完全相同的函数对象,调用instance2.destroy()
和this
也会有不同的destroy
值。如果您明确呼叫this
,myLib.prototype
将myLib.prototype.destroy()
的唯一情况就是{。}}。