我不知道如何说出标题,但这里有一个例子,它让我大吃一惊
myLib.prototype._handlers = {}; myLib.prototype.destroy = function () { this._handlers = {}; }
我正在写测试,幸运的是它抓住了这个问题.破坏方法实际上不起作用.
为什么会这样?我认为原型的属性是为每个new myLib
实例创建的,但是从编写这些测试开始,所有 new myLib
实例都有这些处理程序.
您可以在原型上设置非功能.问题是原型上的属性是在对象的所有实例之间共享的.这通常不是您想要的数据属性,但它是您想要的函数属性.
因此,您通常会在对象的构造函数中初始化数据属性,并使它们成为"自己的"属性,这些属性对于每个实例都是唯一的,这通常是您想要的.
我认为原型上的属性是为每个新的myLib实例创建的,但是从编写这些测试开始,所有新的myLib实例都有这些处理程序.
原型是一个对象,用作属性的查找机制.当您引用时var x = obj.prop
,Javascript首先查看obj
对象本身以查看是否存在名为的属性"prop"
.如果有,那被认为是"自己的"属性,并且它的值被取出.如果没有,那么它转到原型对象以查看它是否具有名为的"自己"属性"prop"
.如果是,则返回该值.如果它没有那个命名属性,那么它会检查原型对象是否有自己的原型,如果有,它会检查一个,依此类推......
因此,原型用作查找参考.没有复制或创建任何新内容.只有原型的"参考"可以用于查找.这就是原型在所有实例之间共享的原因.出于多种原因,它是故意设计的.一个原因是它的存储效率.所有实例只共享一个原型对象,因此所有这些引用都不必在每个对象实例上重复.
当您使用以下内容分配属性时:
obj.someProp = "foo";
它只会影响"自己的"财产.它不会影响原型.如果名为的对象上有"own"属性"someProp"
,则更新它的值.如果没有,则在实际对象实例上创建新的"自己的"属性.如果原型上有这个名称的属性,那么该值现在基本上是隐藏的,因为Javascript属性查找方案将首先找到"own"属性,然后将使用该属性(只要它存在).
了解在.destroy()
方法中分配属性时可能也很重要,例如:
myLib.prototype._handlers = {}; myLib.prototype.destroy = function () { this._handlers = {}; }
myLib.prototype._handlers
执行该obj.destroy()
方法时,这实际上并没有触及该值.相反,this._handlers = {};
在对象的实际实例上创建一个新属性,即"自己的"属性.任何引用都this._handlers
将首先找到"自己的"属性,这将是从那时开始使用的属性所以它可能"似乎"改变原型值,但新的"自己"属性只是掩盖了原型值.