function Person(name) {
this.name = name;
}
var p1 = new Person("张三");
Person.prototype.greeting = function () {
return "你好,我叫" + this.name;
};
p1.name; // 张三
p1.greeting(); // 你好,我叫张三
p1.constructor === Person; // true
/* so far so good, but... */
Person.prototype = {
say: function () {
return "你好,我叫" + this.name;
}
};
p1.say(); // TypeError: Object #<Person> has no method 'say'
p1.constructor.prototype; // Object { say: function }
Person 的原型属性里明明有 say 方法,为什么访问不到,求解释,谢谢!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
咦?这个例子好眼熟的说……
因为你在实例化
p1
以后覆盖了原型对象(用一个新的对象字面量赋值了),而p1
拥有的是指向旧的原型对象的指针。另外,
p1.constructor
指向的是构造器本身,所以它可以获取到新的原型对象。如果你用Person.prototype.say = function () {...}
的方式去追加方法(这就不是覆盖了),那么p1.say()
就会正常访问。BTW,在覆盖的前提下也可以这样访问到:
Person的prototype被新创建的{say: function() {...}}覆盖后,
p1引用的原型对象仍然指向Person之前旧的那个prototype对象。
所以调用p1.say();在原型链找不到这个方法
new Person()
的过程实际上执行了3步操作然后o被赋值给了p1,p1实际上是通过
__proto__
属性来访问Person.prototype
,p1在访问一个属性的时候,会先在自己的属性里查找,如果没有的话会查找p1.__proto__
指向的原型对象,后来Person.prototype
被改写了,但是p1.__proto__
还是指向了原先的原型对象,所以访问不到say方法因为
p1
在new
的时候Person.prototype
指向X
(这里X
是代称).其中,
X.greeting
是一个你自定义的函数.这个时候
p1.__proto__ === X
, 所以p1.greeting
可以正常访问.然后, 你改
Person.prototype
指向Y
(这里Y
是代称), 这里就是关键!其中,
Y.say
是一个你自定义的函数.但这个时候
p1.__proto__ === X
仍然为真(也就是说p1.__proto__ !== Y
), 所以此时p1.greeting
仍可以正常执行, 但p1.say
是不可以(因为X
里面没有say
这个函数).另外, 如果最后你再做一个
p2 = new Person("李四");
,p2.say
是可以的(因为p2.__proto__ === Y
), 但是p2.greeting
是不可以的.