JS继承相关
本文介绍js继承的几种方法
1. 原型链继承
利用js的原型链,访问实例对象上不存在但是原型对象中存在的属性和方法。缺点就是假继承。父类的引用属性是共享的。
const Parent = function () {
this.name = 'parent'
this.children = ['son1', 'son2']
}
Parent.prototype.getChildren = function() {
console.log('儿子们:', this.children)
}
const Children = function () {
}
Children.prototype = new Parent()
const child = new Children()
child.children.push('bitch')
child.getChildren()
const child2 = new Children()
child2.children.push('bitch2')
child2.getChildren()
child.getChildren()
// 儿子们: [ 'son1', 'son2', 'bitch' ]
// 儿子们: [ 'son1', 'son2', 'bitch', 'bitch2' ]
// 儿子们: [ 'son1', 'son2', 'bitch', 'bitch2' ]
创建的child实例是通过new Children得到的,new操作符的内部会做两件事,基于构造函数原型创建一个空对象,然后改变this指向让属性私有化。因为我们将Children构造函数的原型对象改成了Parent的一个实例,那么,当我们通过new Children得到的对象,其_proto_实际指向Parent的原型对象。即:new Children得到的所有实例,继承得到的该属性都是Parent构造函数的原型对象拥有的,仅此一份,大家共有。
缺点:通过原型链实现继承,缺点显而易见,祖父对象的引用类型属性值,都是子孙公共访问与更改的。因为子孙对象不管是使用祖先的方法还是属性,改的都是祖先构造函数的原型对象。注意:原型对象的方法能够访问,但是引用类型共享
2. 构造函数继承
// 2. 借用构造函数:子构造函数call到父类
const Parent = function () {
this.name = 'baba'
this.children = ['son1', 'son2']
this.getChildren = function () {
console.log('儿子们:', this.children)
}
}
const Children = function(...args) {
//call等方法,类似于class中的constructor函数,自动初始化
Parent.call(this, ...args)
}
const child1 = new Children()
child1.children.push('bitch1')
child1.getChildren()
const child2 = new Children()
child2.children.push('bitch2')
child2.getChildren()
child1.getChildren()
该方法,实际上通过调用call方法改变了this指向。避免了引用类型的属性被所有实例共享。缺点:该方法得到的实例对象,无法访问父类原型对象上的方法
3. 组合继承
利用原型链继承获得父类原型对象上的方法,通过构造函数继承实例化私有属性
const Parent = function(){
this.children = ['son1', 'son2']
}
Parent.prototype.getChildren = function () {
return this.children
}
const Children = function (...args) {
Parent.call(this, ...args)
}
Children.prototype = Parent.prototype
const child = new Children()
const child2 = new Children()
console.log('child.__proto__', child.__proto__)
child.children.push('nima')
child2.children.push('nima2')
console.log('child.getName():', child.getChildren())
缺点:
1.通过打印发现实例的构造函数不是Children,而是Parent
2.调用两次Parent,据说影响性能
4.组合继承改进版本–寄生继承
const Parent = function(){
this.children = ['son1', 'son2']
}
Parent.prototype.getChildren = function () {
return this.children
}
const Children = function (...args) {
Parent.call(this, ...args)
}
Children.prototype = Object.create(Parent.prototype)
Children.prototype.constructor = Children
const child = new Children()
const child2 = new Children()
console.log('child.__proto__', child.__proto__)
child.children.push('nima')
child2.children.push('nima2')
console.log('child.getName():', child.getChildren())
主要是当我们打印实例的构造器constructor,能够返回Children而不是Parent。
5. es6继承
class Parent {
constructor (props) {
this.name = props
}
getName () {
console.log(this.name)
}
}
class Children extends Parent {
constructor (name, old) {
super(name)
this.old = old
}
getOld () {
console.log(this.old)
}
}
const child = new Children('hhvcg', 12)
child.getName()
child.getOld()
完结散花
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
