终于搞懂了JS的继承方法(1)
以前一直没有弄懂js的继承方法,今天重新看了大红书后,终于明白了几种继承方法优点与缺点。
1、原型链继承
先看大红书上面的一段代码:
function SuperType(){
this.color = ['red','blue','green']
this.number = 1
}
function SubType(){
}
//继承SuperType
SubType.prototype = new SuperType()
通过把SubType的原型变成了SuperType的一个实例,这样SubType就继承了SuperType了color的属性。我们接下来再创建两个实例看一下这种继承产生的问题。
let instance1 = new SubType()
instance1.color.push('black')
instance1.number++
console.log(instance1.color) //['red','blue','green','black']
console.log(instance1.number) //2
let instance2 = new SubType()
console.log(instance2.color) //['red','blue','green','black']
console.log(instance2.number) //1
在创建SubType实例instance1后,我们再修改color属性后,再创建instance2实例后,会发现instance2的color属性会是修改后的值,而number属性却是正常的,这是因为color是引用属性,创建实例后,实例对于引用属性只是进行浅复制,无论创建多少个实例它们的color都会指向同一个地址空间。所以我们再继承时,并不会单独使用原型链继承。
2、盗用构造函数
此方法就是在子类的构造函数中调用父类的构造函数,所以就是使用call() 和apply() 方法以创建的对象为上下文的构造函数
function SuperType(){
this.color = ['red','blue','green']
this.number = 1
}
function SubType(){
SuperType.call(this)
}
这样子类就可以继承父类的属性,也可以向父类进行传递参数:
function SuperType(name){
this.color = ['red','blue','green']
this.number = 1
this.name = name
}
function SubType(){
SuperType.call(this,'junker')
}
let instance1 = new SubType()
console.log(instance1.name) //junker
这种继承方法也不会单独使用,因为这样父类上面定义的方法,子类是无法访问到的。
3、组合继承
综合以上两种继承方式,将两种方法的优点结合起来。基本的思路是使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。这样可以把方法定义在原型上以实现重用,又可以让每个实例都有自己的属性。
function SuperType(name){
this.color = ['red','blue','green']
this.number = 1
this.name = name
}
function SubType(){
SuperType.call(this,'junker')
}
SubType.prototype = new SuperType()
这样在父类定义一个方法,子类也可以使用
let instance1 = new SubType();
instance1.color.push('black')
console.log(instance1.color); //[ 'red', 'blue', 'green', 'black' ]
instance1.sayHi() //hi
let instance2 = new SubType()
console.log(instance2.color); //[ 'red', 'blue', 'green' ]
instance1.sayHi() //hi