继承分类
1.类式继承
原理:重写子类的原型,代之以父类的实例。
function Father(name) {
this.faName = name
this.faAge = 28
this.friend = ['zs','ls','ww']
}
const a = new Father('wumao')
function Son(name) {
this.sonName = name
this.sonAge = 6
}
Son.prototype = new Father()
const b = new Son('liumao')
const c = new Son('qimao')
console.log(a);
console.log(b);
console.log(b.faAge); // 28
b.faAge = 29
b.friend.push('lm')
console.log(b.friend); // [ 'zs', 'ls', 'ww', 'lm' ]
console.log(c.faAge); // 28
// 缺点:当引用数据类型被修改 会影响到他所有的实例对象
console.log(c.friend); //[ 'zs', 'ls', 'ww', 'lm' ]
console.log(a instanceof Father); // true
console.log(b instanceof Father); // true
console.log(b instanceof Son); // true
缺点
- 当继承父类的时候,当有复杂数据类型的时候,修改复杂类型的数据时,会修改到所有的实例对象
- 无法传递参数,当创建子类型实例的时候,不能向父类构造函数中传递参数
2.构造函数式继承(经典继承)
原理:通过之类的内部通过call,apply去执行要继承的父类
function Father(name) {
this.faName = name
this.faAge = 28
this.friend = ['zs', 'ls', 'ww'],
Father.prototype.hello = 'hello world'
}
function Son(name) {
Father.call(this,name)
this.sonName = name
this.sonAge = 6
}
const a = new Son('haha')
console.log(a);
console.log(a instanceof Father); //false
console.log(a instanceof Son); //true
console.log(a.hello); // undefined
缺点
- 不能通过instanceof检测到继承来自父类
- 不能使用父类的原型上的属性和方法
3.组合式继承
既然类式继承和构造函数式继承都有缺陷,那我们就进行组合一起
function Father(name) {
this.faName = name
this.faAge = 28
this.friend = ['zs', 'ls', 'ww'],
Father.prototype.hello = 'hello world'
}
function Son(name) {
Father.call(this,name)
this.sonName = name
this.sonAge = 6
}
Son.prototype = new Father()
const a = new Son('haha')
console.log(a);
console.log(a instanceof Father); //true
console.log(a instanceof Son); //true
console.log(a.hello); // hello world
缺点
- 父类的构造函数被调用了两次,显得多余
- 创建的实例对象会不仅在对象上创建一份,还会在原型上也创建一份
4.原型式继承
这个本质上其实是对一个对象的浅拷贝,暴露的问题也是,不能传入参数以及引用类型会共享
function createObject(obj) {
function F() {
}
F.prototype = obj;
return new F()
}
var person = {
name: "wumao",
friends: ["liumao", "qimao"]
};
const a = createObject(person)
const b = createObject(person)
缺点:
- 子类实例无法传入参数
- 父类的引用会被所有子类所共享
5.寄生式继承
寄生式继承和原型式继承差不了太多,
它依托于一个内部对象而生成一个新对象,因此称之为寄生。
var person = {
name: 'wumao',
age: 18
}
function createObj(obj) {
const o = Object.create(obj)
o.__proto__.who = function () {
console.log(this.name);
}
return o
}
const c = createObj(person)
c.who()
console.log(c.name);
6.寄生组合式继承
function inherit(child, parent) {
const p = Object.create(parent.prototype)
child.prototype = Object.assign(child.prototype, p)
//还原被污染的constructor
child.prototype.constructor = child
}
// 父类
function Father(name) {
this.fatherName = name
}
Father.prototype.who = function () {
console.log(this.name);
}
// 子类
function Son(wife, fatherName) {
Father.call(this, fatherName) //把属性继承过来
this.wife = wife
this.age = 22
}
inherit(Son, Father) //把原型继承过来
const newObj = new Son('gaga', 'haha')
console.log(newObj.fatherName);
好处
- 继承的属性没有在原型链上.因此不会共用一个属性
- 子类可以动态传入参数
- 父类的构造函数只执行了一次