原型和原型链的概念是js这门语言的基础,一定要掌握
什么是原型
- 每一个函数都有一个
prototype属性,值是一个对象,称为显示原型,当这个函数被作为构造函数时,其原型对象里保存着其实例对象所需要的公有方法和属性,原型对象还保存着一个constructor属性,这个属性会指向自己的构造函数。- 每个实例对象都有一个
__proto__属性,被称为隐式原型,会指向创建它的构造函数的prototype(显示原型),当访问一个对象上的属性的时候首先回到对象的私有属性中去寻找,找不到就会到其隐式原型上去寻找。所以实例对象可以直接使用原型上的公有方法和属性,并且可以通过constructor访问构造器
原型,构造函数,实例对象的关系
- 构造函数通过new操作符去创建一个实例对象
- 构造函数中包含显示原型prototype
- 实例对象中包含隐式原型__proto__ 隐式原型指向构造函数的显示原型prototype
- 原型对象包含constructor属性指向构造函数,还包含一些实例可以访问的公有方法和属性
原型链又是什么
- 首先要明白一个概念,
原型也是一个对象,所以原型也可以作为实例对象拥有自己的隐式原型__proto__- 当我们访问对象的属性的时候,如果在其私有属性和原型对象内都找不到该属性,就会到原型对象的__proto__隐式原型中去寻找,如果还找不到就继续往下一层找,这就是原型链的概念,原型链的尽头就是
Object.prototype.__proto__值是null
继承
继承的方式有哪些
原型链继承
- 原理:改写原型指向超类型的实例,实现公有属性和私有属性的继承
- 缺点:不能传递参数,私有属性如果是引用数据类型,会造成修改混乱,因为每一个子级实例修改这个对象都会影响到其它的实例
function Son(){}
function Fa(){
this.name = "Fa"
}
Fa.prototype.age = 12
Son.prototype = new Fa()
new Son().name // "Fa"
new Son().age // 12
盗用构造函数继承
- 原理: 在构造函数中通过call去调用超类型的构造函数并将this指向自己
- 缺点: 不能继承原型上的属性,由于是在构造函数内部完成 所以不能复用
function Fa(){
this.name = "Fa"
}
function Son(...args){
Fa.call(this,...args)
}
Fa.prototype.age = 12
new Son().name // "Fa"
new Son().age // undefined
组合继承
- 原理:结合借用构造函数和原型链继承
- 缺点:调用了两次超类型的构造函数 所以多出来一些不必要的私有属性,造成额外的性能消耗
function Fa(){
this.name = "Fa"
}
function Son(...args){
Fa.call(this,...args)
}
Fa.prototype.age = 12
Son.prototype = new Fa()
new Son().name // "Fa"
new Son().age // 12
原型继承
- 原理: 改写原型的指向,和原型链继承类似,可以继承公有和私有属性
- 缺点:同原型链继承
function Factory(obj) {
// 这里也是直接创建了一个实例对象,也可以采用构造函数的方式
// function a(){}
// a.prototype = obj
// return new a()
const a = {};
a.__proto__= obj
return a
}
const obj = Factory([1,2,3])
obj.length // 3
寄生继承
- 原理:在原型继承的基础上对子级实例进行增强
- 缺点:同原型链
function Factory(obj) {
const a = {};
a.__proto__= obj
a.__proto__.getAge = function (){
return 12
}
return a
}
const obj = Factory([1,2,3])
obj.getAge() // 12
寄生组合式继承
- 原理:结合借用构造函数和寄生继承
- 缺点:无
- 寄生继承只继承超类型的原型而不是实例,全程只调用一次父级构造函数,并将constructor指向自己的构造函数
function Fa(){
this.name = "Fa"
}
function Son(...args){
Fa.call(this,...args)
}
Son.prototype = Object.create(Fa.prototype)
Son.prototype.constructor = Son
Fa.prototype.age = 12
extends (es6,用于class中)
- 原理和寄生组合式继承类似,也有一点区别就不讲了