什么是原型链?
几个概念,构造函数、原型、实例
- 每个构造函数都有一个prototype指向原型对象
- 原型对象的constructor指向构造函数
- 每个实例都包含一个指针_proto__指向其原型,有个constructor指向其构造函数
- 访问属性或方法会由原型链,一层层向上查找到顶层 Object.prototype
- Object的原型指向null
继承
原型链继承
function SuperType(){
this.property = true
}
SubType.prototype = new SuperType()
// 修复原型链继承 constructor指向问题
Object.definePrototype(SubType.prototype,'constructor',{
enumerable:false,
value:SubType,
writable:true
})
缺点:
- 原型中包含的引用值会在所有实例中共享,属性要在构造函数定义,不在原型上,以防共享。
- 子类型在实例化时不能给父类型的构造函数传参。
盗用构造函数
function SuperType(name){
this.name = name
}
function Subtype(){
SuperType.call(this,'zhangsan') // 可传参
}
缺点:
- 必须在构造函数中定义方法,子类不能访问父类原型上定义的方法
组合继承(原型链+构造函数)
function SuperType(name){
this.name = name;
this.color = ['red','blue']
}
SuperType.prototype.sayNamr = function(){
console.log(this.name)
}
function Subtype(name,age){
SuperType.call(this,name) // 可传参
this.age = age
}
SubType.prototype = new SuperType();
tip:综合原型链及构造函数,使用最多
原型式继承
function object(o){
function F(){}
F.protoitype = o;
return new F()
}
<!--es5后-->
使用Object.create(person,{
name:{
value:'greg'
}
})
- 不需要单独创建构造函数,由实例直接构建,属性中包含的引用值始终共享。
寄生式继承
function createAnother(o){
let clone = object(o);//调用函数创建新对象
clone.sayhi = function(){//增强对象
console.log('hi')
}
return clone
}
- 在原型式基础上加上新方法,类似构造函数,新方法难以重用
寄生式组合继承
function inheritPrototype(subType,superType){
let prototype = object(superType.prototype);//调用函数创建新对象
prototype.constructor - subType;//增强对象
subType.prototype = prototype
}
function SuperType(name){
this.name = name;
this.color = ['red','blue']
}
SuperType.prototype.sayNamr = function(){
console.log(this.name)
}
function Subtype(name,age){
SuperType.call(this,name) // 可传参
this.age = age
}
inheritPrototype(SubType,SuperType)
类(es6)
class Foo{
//构造函数
constructor(){}
//访问和设置访问器
get name(){
return this.name_
}
set name(newName){
this.name_ = newName
}
静态类方法
static indentify(){}
}
class Bus extends Foo{
//super 可在构造函数,实例方法,静态方法内部使用
constructor(){
//调用父类构造函数,不要在super之前使用this
super()
}
static identify(){
super.identify()
}
}
//类混入实现我多类继承
class Vehicle{}
let FooMixin = (Superclass)=>class extends Superclass{
foo(){
console.log('foo')
}
}
let BarMixin = (Superclass)=>class extends Superclass{
bar(){
console.log('foo')
}
}
function mix(BaseClass,...Mixins){
return Mixins.reduce((accumulator,current)=>current(accumulator),BaseClass)
}
class Bus extends Mix(Vehicle,FooMixin,BarMixin)