1. 概述
原型链是JS中实现继承的重要概念,在我看来,原型链可以认为是一个继承链;
获取某个对象属性或方法时,该对象没有的话,会在其原型链中依次查找,直到原型链终点Object.prototype.__proto__。
2. 什么是原型
- 原型是一个对象;
- 所有对象都有隐式原型(__proto__);
- 所有函数都有显示原型(prototype);
- 函数本身也是一个对象,也有(__proto__);
- 所有对象的__proto__都指向其构造函数的prototype。
3. 原型规则
- Number、String、Boolean、Array、Function、RegExp、Date、Object等的实例对象都有__proto__;
- Null和undefined没有__proto__;
- 获取对象的某个属性或方法时,该对象没有,就会去其__proto__中找;而__proto__也是一个对象,__proto__没有就会去__proto__.__proto__中继续找,直到终点null;这就是原型链。
// 1.数字
var a = 1
a.__proto__ == Number.prototype // true
// 2.字符串
var b = ""
b.__proto__ == String.prototype // true
// 3.布尔值
var c = true
c.__proto__ = Boolean.prototype // true
// 4.NaN(不是数字的数字)
var d = NaN
d.__proto__ = Number.prototype // true
// 5.null和undefind没有原型
// 6.数组
var arr = [];
arr.__proto__ === Array.prototype // true
// 7.函数
var fun = () => {}
fun.__proto__ == Function.prototype // true
// 8.正则
regexp = /\?/
regexp.__proto__ == RegExp.prototype // true
// 9.对象
obj = {}
obj.__proto__ == Object.prototype // true
4. 利用原型链实现继承
- 在构造函数中给this添加的属性/方法,直接属于实例对象;
- 在构造函数的prototype添加的属性/方法,属于实力对象的__proto__;
- 在new出实例对象后,修改其构造函数的prototype中的属性/方法依然能影响到该对象。
// 父类型
function Animal() {
// 属于dog.__proto__
this.name = "animal";
this.eat = function() {
console.log(this.name, "吃...");
}
}
// 属于dog.__proto__.__proto__
Animal.prototype.sleep = function(){
console.log(this.name, "睡...");
}
// 子类型
function Dog() {
// 直属dog的属性/方法
this.name = "dog";
this.run = function() {
console.log(this.name, "跑...");
}
}
// Dog去继承Animal
Dog.prototype = new Animal();
var dog = new Dog();
dog.run(); // dog跑...
dog.eat(); // dog吃...
dog.sleep();// dog睡...
// 属于dog.__proto__
Dog.prototype.sing = function(){
console.log(this.name, "唱歌...");
}
// 属于dog.__proto__.__proto__
Animal.prototype.dance = function(){
console.log(this.name, "跳舞...")
}
dog.sing(); // dog唱歌...
dog.dance();// dog跳舞...
// dog的原型链
dog.__proto__ == Dog.prototype
dog.__proto__.__proto__ == Dog.prototype.__proto__ == Animal.prototype
dog.__proto__.__proto__.__proto__ == Animal.prototype.__proto__ == Object.prototype
dog.__proto__.__proto__.__proto__.__proto__ == Object.prototype.__proto__ = null
5. 原型链
// 1.等价于Dog.prototype
dog.__proto__
// Animal {name: "animal", eat: ƒ}
// 2.等价于Animal.prototype
dog.__proto__.__proto__
// {sleep: ƒ, constructor: ƒ}sleep: ƒ ()constructor: ƒ Animal()__proto__: Object
// 3.等价于Object.prototype
dog.__proto__.__proto__.__proto__
// {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
// 4.终点Object.prototype.__proto__为null
dog.__proto__.__proto__.__proto__.__proto__
// null