如果属性存在于对象实例上,即使它的原型发生了变化,它们怎么样

时间:2015-03-20 05:55:57

标签: javascript

当我执行下面的代码时,我预计最后一个语句会给我未定义,但是p1.lastname仍然有一个值。有人可以解释一下吗?

function Person() {
  this.name = "myname";
}
var p1 = new Person;
console.log(p1.name); // prints "myname"
Person.prototype.lastname = "mylastname";
console.log(p1.lastname); // prints "mylastname"
Person.prototype = {};
console.log("still there? " + p1.lastname); // prints "still there? mylastname"

2 个答案:

答案 0 :(得分:1)

实际上,prototype属性在JavaScript世界中具有意义,但它仍然是一个常规属性,它是对表示原型的对象的引用。

也就是说,当您使用具有prototype属性的对象设置lastname,然后创建Person的实例时,将使用{{从原型对象创建此对象1}}属性。整个人都参考了这个原型对象。

即使您更改lastname原型,Person变量仍然是对使用旧原型实例化的对象的引用,它保留对此原型的引用,而不是新原型的引用。 / p>

如果您尝试创建p1变量并再次实例化p2,则将使用空原型对象构建此新人。

回答一些OP评论......

  

感谢@Matías,创建一个新的Person实例没有姓氏   属性。我还不明白的是你说的时候   用一个具有lastname属性的对象设置原型,然后你   创建Person的实例,这个对象是从   具有lastname属性的原型对象但我先创建了   在我添加&之前的实例删除/覆盖lastname属性。 -

是的,但我发现这里没有区别。

正如我在回答中所说,原型是常规对象,Person属性是任何prototype实例的常规属性。

例如,如果您已定义构造函数function,则它具有默认原型 - 没有属性的对象 - 。 使用function A() {}实例化的任何对象将共享相同的原型,因此,如果在实例化任何A后向原型添加属性,则这些实例将具有该属性,因为{ {1}}属性是对同一原型对象的引用。

当你重新分配A属性时,你设置了另一个对象,总而言之,现在prototype的任何实例仍将引用前一个原型,因为它们是使用第一个原型对象实例化的,不是第二个。

答案 1 :(得分:0)

回答你向Matías提出的问题(由于我还没有足够的声誉,我无法发表评论),将Person.prototype设置为{}使得Person.prototype不再是对p1原型的引用。但是如果你通过语句将Person.prototype重新分配给它的原始值,Person.prototype = Object.getPrototypeOf(p1); ,对Person.prototype.lastname的更改将再次影响p1(只要p1继续没有自己的lastname属性。)

var p1 = new Person();
Person.prototype.lastname = "mylastname";
console.log(p1.lastname); // prints "mylastname"
Person.prototype = {};
Person.prototype.lastname = "mynewlastname";
console.log(p1.lastname); // still prints "mylastname"
Person.prototype = Object.getPrototypeOf(p1);
Person.prototype.lastname = "mynewlastname";
console.log(p1.lastname); // now prints "mynewlastname"

这类似于将对象的引用传递给函数时发生的情况:在函数外部可以看到重新分配,删除或向对象添加新属性。但重新分配引用变量本身将取消链接,以便它不再影响相关的原始对象。