JS中原型和原型链这一知识点一直是考察和理解JS的重点
每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。
一、 构造函数、实例对象和原型对象
上面这张图可以很好的帮我们理清构造函数、实例对象和原型对象之间的关系
- 首先,构造函数有一个prototype属性指向它的原型对象;
- 所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针,即指向构造函数;
- 由构造函数new出来的实例对象,该实例的内部将包含一个指针(内部
属性),指向构造函数的原型对象。ECMA-262 第 5 版中管这个指针叫[[Prototype]]。在Firefox、 Safari 和 Chrome 在每个对象上都支持一个属性
_proto_; - 总结来说,prototype是构造函数的属性,_proto_是实例对象的属性
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true
在上述代码中,有构造函数Person、实例对象person1、实例对象person2、Person的原型对象,这里实例对象person1、person2和其构造函数没有太大联系,其关系图可以表示如下:
两个函数
- isPrototypeOf()
- 判断A.isPrototypeOf(B):A是否是B的原型
alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true
- 判断A.isPrototypeOf(B):A是否是B的原型
- Object.getPrototypeOf()
- 获取Object.getPrototypeOf(B):获取B的原型
alert(Object.getPrototypeOf(person1)==Person.prototype);//true
alert(Object.getPrototypeOf(person1).name); //"Nicholas"
- 获取Object.getPrototypeOf(B):获取B的原型
二、原型链
JS中万物皆对象,每个对象都有一个([[prototype]])_proto_属性,指向它的原型对象,而这个原型对象也有_proto_属性,指向它自己的原型对象,这样一步步就形成了原型链(一条链子串起来的原型对象)
在查找某个对象的属性时,首先会在该对象内进行查找,如果找到就返回该属性值;否则,会在该对象的原型对象中继续查找,找不到的话再去原型对象的原型对象中进行查找,直到原型链的尾部。这样层层向上直到一个对象的原型对象为Object。
所有自定义类型都会继承toString()、valueOf()等默认方法,是因为它们都默认继承Object。
参考:
- MDN https://developer.mozilla.org/zhCN/docs/Web/JavaScript/Inheritance_and_the_prototype_chain
- 《JavaScript高级程序设计第3版》