替换原始原型对象后,为什么旧​​的原型属性仍然可用

时间:2014-07-25 09:38:09

标签: javascript prototype

我知道Prototype属性本质上是动态的,对象只传递相同的引用。无论何时更改它们,都会在运行时显示更改的结果。但是在重新定义原型对象的情况下,在重新定义原型之前创建的对象仍然指向旧的原型对象。以这个例子为例:

var Person=function(firstName,lastName)
{
    this.firstName=firstName;
    this.lastName=lastName;
} 

Person.prototype.getFullName=function()
{
    return this.firstName+" "+this.lastName;
}
var student=new Person("Ankur","Aggarwal");
student.getFullName() //returns "Ankur Aggarwal"

Person.prototype.getFullName=function()
{
    return "I am changed";
}

student.getFullName() //returns "I am changed"

直到这里我理解了这个场景。但是,如果我再次重新定义原型,学生并没有指向新的原型。它仍指向旧原型

Person.prototype={}
student.getFullName() //still works why?

我在网上搜索了这个,但无法理解。请帮帮我

1 个答案:

答案 0 :(得分:1)

由于创建的实例与Person.prototype 属性之间没有直接链接,因此只是它所引用的对象。执行new Person()时,生成的实例的基础原型设置为对象Person.prototype,此时引用

这也是我在这里得到5的原因:

var a = [1, 2, 3, 4, 5];
var b = a;
var a = []
console.log(b.length);

ASCII-art可以在这里提供帮助。 : - )

最初,您拥有Person函数,其prototype属性引用具有getFullName函数的对象:

+-----------+
|  Person   |
+-----------+     +-------------+
| prototype |---->|  (object)   |
+-----------+     +-------------+     +------------+
                  | getFullName |---->| (function) |
                  +-------------+     +------------+
                                      | ...        |
                                      +------------+

然后使用var student=new Person("Ankur","Aggarwal");创建一个实例:

+-----------+
|  Person   |
+-----------+     +-------------+
| prototype |--+->|  (object)   |
+-----------+  |  +-------------+     +------------+
               |  | getFullName |---->| (function) |
               |  +-------------+     +------------+
+-----------+  |                      | ...        |
|  student  |  |                      +------------+
+-----------+  |
| __proto__ |--+
| ...       |
+-----------+

然后你给Person.prototype一个新值,但这对student与其基础原型的连接没有影响:

+-----------+
|  Person   |
+-----------+     +-------------+
| prototype |---->|  (object)   |
+-----------+     +-------------+

+-----------+
|  student  |
+-----------+      +-------------+
| __proto__ |----->|  (object)   |
| ...       |      +-------------+     +------------+
+-----------+      | getFullName |---->| (function) |
                   +-------------+     +------------+
                                       | ...        |
                                       +------------+

旁注:__proto__不是字面上的属性名称,尽管从ES6开始。在ES5及更早版本中,除了具有非标准扩展名的引擎外,对象的基础原型不能作为属性访问。


我说实例和Person.prototype之间没有直接链接,这是真的。有一个间接链接,但它与问题无关。如果你不是学生,请立即停止阅读。好的,对于你的学员:初始对象Person.prototype引用的是一个属性constructor,引用Person。因此,即使Person.prototype更新后,student也会链接到其原型,该原型的constructor属性引用Person,其中Person.prototype为{{1}}。不影响这个问题,但我想我会提到它。