为什么添加原型的不同方式会影响?

时间:2017-01-26 16:10:16

标签: javascript

我正在运行以下代码,

function Person(){}
var person1 = new Person();
Person.prototype= {
    name : "Ann",
    sayName : function(){
        console.log( this.name);
    }
}
 person1.sayName();

它将显示错误“对象#没有方法'sayName'”。这会导致错误,因为person1指向的原型不包含该名称的属性。 我的问题是当我改变我定义原型的方式如下:

function Person(){}
var person1 = new Person();
Person.prototype.name = "Ann";
Person.prototype.sayName = function(){
    console.log(this.name);
}
person1.sayName();

它与“Ann”正确运行。谁能告诉我为什么会这样?谢谢。

3 个答案:

答案 0 :(得分:6)

当你实例化一个"类"使用new Person,将为新对象分配Person.prototype的值,例如类似的东西:

person1.__proto__ = Person.prototype

(不是,仅用于说明目的。)

这意味着person1.__proto__Person.prototype 指向同一个对象。

如果你然后用Person.prototype完全替换 Person.prototype = { ... },那么实例的原型和类原型就不再指向同一个对象了。

但是,如果您使用Person.prototype.name = ... 修改现有原型,则两者都会继续指向相同(现在已修改)的对象。

答案 1 :(得分:0)

因为在person1的实例化时,原型扩展尚未被评估,换句话说 - 在原型声明之后重新排序person1的实例

function Person(){}

var person1 = new Person();

Person.prototype= {
    name : "Ann",
    sayName : function(){
        console.log( this.name);
    }
}

var person2 = new Person();

// person1.sayName(); // fails
person2.sayName(); // works

答案 2 :(得分:0)

在第一种情况下,您将Person声明为函数。然后,您将创建一个名为person1的实例,该实例继承Person.prototype。然后,您将Person.prototype设置为新对象,因此person1.prototype和Person.prototype现在引用不同的对象。然后你尝试做.sayName()并且它不起作用,因为person1.prototype仍然是空的。

在第二种情况下,您只需设置属性,而不是重新定义Person.prototype。这样,person1对原型的引用仍然与Person.prototype相同,这就是为什么当你执行.sayName()时它的工作原理。

如果移动var person1 = new Person();在设置原型之后,第一个选项也将起作用,因为person1将继承对Person.prototype的新引用而不是旧引用。