当我执行下面的代码时,我预计最后一个语句会给我未定义,但是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"
答案 0 :(得分:1)
实际上,prototype
属性在JavaScript世界中具有意义,但它仍然是一个常规属性,它是对表示原型的对象的引用。
也就是说,当您使用具有prototype
属性的对象设置lastname
,然后创建Person
的实例时,将使用{{从原型对象创建此对象1}}属性。整个人都参考了这个原型对象。
即使您更改lastname
原型,Person
变量仍然是对使用旧原型实例化的对象的引用,它保留对此原型的引用,而不是新原型的引用。 / p>
如果您尝试创建p1
变量并再次实例化p2
,则将使用空原型对象构建此新人。
感谢@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"
这类似于将对象的引用传递给函数时发生的情况:在函数外部可以看到重新分配,删除或向对象添加新属性。但重新分配引用变量本身将取消链接,以便它不再影响相关的原始对象。