原型链继承
子类的原型指向父类的一个实例。
function Parent(age) { this.name = 'parent' this.isShow = true this.colors = ['red', 'pink', 'blue'] this.age = age }
Parent.prototype.getInfo = function () { console.log(this.name, this.isShow, this.colors, this.age) }
function Child(age) { }
Child.prototype = new Parent()
const children1 = new Child(18) children1.name = 'newName' children1.isShow = false children1.colors.push('black') children1.getInfo()
const children2 = new Child(20) children2.getInfo()
|
优点:父类方法可以复用
缺点:
- 父类中的引用类型属性会被篡改。
- 子类实例不能给父类构造函数传参。
借用构造函数继承
使用 call() 和 apply() 方法,在子类构造函数中调用父类构造函数。
function Parent(age) { this.name = 'parent' this.isShow = true this.colors = ['red', 'pink', 'blue'] this.age = age this.say = () => { console.log(this.name + ' 说了你好!') } }
function Child(age) { Parent.call(this, age) }
const children1 = new Child(18) children1.name = 'newName' children1.isShow = false children1.colors.push('black') children1.say() console.log(children1.name, children1.isShow, children1.age, children1.colors)
const children2 = new Child(20) children1.say() console.log(children2.name, children2.isShow, children2.age, children2.colors)
|
优点:
- 父类中的引用类型属性不会被篡改。
- 子类实例可以给父类构造函数传参。
缺点:
- 不能复用,每个子类都有父类实例的副本,影响性能。
- 只能继承父类实例的 属性和方法,不能继承原型上的属性和方法,因此所有方法都写在构造函数中,每次创建实例都会初始化。
组合继承
组合继承综合了 原型链继承 和 构造函数继承,将两者的优点结合了起来。
基本的思路:使用原型链继承原型上的属性和方法,而通过构造函数继承实例属性,这样既可以把方法定义在原型上以实现复用,还能让属性不被共享。
function Parent(age) { this.name = 'parent' this.isShow = true this.colors = ['red', 'pink', 'blue'] this.age = age this.say = () => { console.log(this.name + ' 说了你好!') } }
Parent.prototype.getInfo = function () { console.log(this.name, this.isShow, this.age, this.colors) }
function Child(age) { Parent.call(this, age) }
Child.prototype = new Parent()
Child.prototype.constructor = Child
const children1 = new Child(18) children1.name = 'newName' children1.isShow = false children1.colors.push('black') children1.getInfo()
const children2 = new Child(20) children2.getInfo()
|
优点:
- 父类方法可以复用
- 父类中的引用类型属性不会被篡改。
- 子类实例可以给父类构造函数传参。
原型式继承
利用一个空对象作为中介,将某个对象直接赋值给空对象构造函数的原型。
function object(obj) { function F() { } F.prototype = obj return new F() }
|
object()对传入其中的对象执行了一次 浅复制,将构造函数 F 的原型直接指向传入的对象。
function object(obj) { function F() { } F.prototype = obj return new F() }
const obj = { name: '张三', colors: ['red', 'pink', 'blue'], say() { console.log(this.name + ' 说了你好!' + '颜色有:' + this.colors) } }
const obj1 = object(obj) obj1.name = 'newName' obj1.colors.push('black') obj1.say()
const obj2 = object(obj) obj2.say()
|
优点:父类方法可以复用
缺点:
- 父类中的引用类型属性会被篡改。
- 子类实例不能给父类构造函数传参。
ES5 中存在 Object.create() 的方法,能够代替上面的object方法。
const obj = { name: '张三', colors: ['red', 'pink', 'blue'], say() { console.log(this.name + ' 说了你好!' + '颜色有:' + this.colors) } }
const obj1 = Object.create(obj) obj1.name = 'newName' obj1.colors.push('black') obj1.say()
const obj2 = Object.create(obj) obj2.say()
|
寄生式继承
使用原型式继承对一个目标对象进行浅复制,增强这个浅复制的能力,返回构造函数。
function object(obj) { function F() { } F.prototype = obj return new F() }
function createAnother(original) { const clone = object(original) clone.getName = function () { console.log(this.name) } return clone }
const obj = { name: '张三', colors: ['red', 'pink', 'blue'], say() { console.log(this.name + ' 说了你好!' + '颜色有:' + this.colors) } }
const obj1 = createAnother(obj) obj1.name = 'newName' obj1.colors.push('black') obj1.say() obj1.getName()
const obj2 = createAnother(obj) obj2.say() obj2.getName()
|
优点:父类方法可以复用
缺点:
- 父类中的引用类型属性会被篡改。
- 子类实例不能给父类构造函数传参。
寄生组合式继承
组合继承综合了 构造函数传递参数 和 寄生模式 实现继承。
寄生式组合继承可以算是引用类型继承的最佳模式,是最成熟的方法,也是现在库实现的方法。
function object(obj) { function F() { } F.prototype = obj return new F() }
function inheritPrototype(child, parent) { const prototype = object(parent.prototype) prototype.constructor = child Child.prototype = prototype }
function Parent(age) { this.isShow = true this.name = 'parent' this.colors = ['red', 'pink', 'blue'] this.age = age this.say = () => { console.log(this.name + ' 说了你好!') } }
Parent.prototype.getInfo = function () { console.log(this.name, this.isShow, this.colors, this.age) }
function Child(age) { Parent.call(this, age) }
inheritPrototype(Child, Parent)
const child1 = new Child(18) child1.name = 'newName' child1.colors.push('black') child1.say() child1.getInfo()
const child2 = new Child(20) child2.say() child2.getInfo()
|
ES6类继承extends
class Parent { constructor(age) { this.name = '张三' this.age = age this.colors = ['red', 'pink', 'blue'] }
getInfo() { console.log(this.name, this.age, this.colors) } }
class Child extends Parent { constructor(age) { super(age) } } const child = new Child(18) child.getInfo()
|
个人简介:脆弱的种子在温室也会死亡,坚强的种子,在沙漠也能发芽。