继承也是js八股文中常考的问题,本文主要介绍了js中实现继承的五种方法,帮助大家更好的理解和使用JavaScript,感兴趣的朋友可以了解下
原型链继承
原理就是子类的原型对象指向父类的实例
// 父类
function Parent() {
this.name = '父类';
this.introduce = function () {
console.log('my name is' + this.name);
};
}
// 子类
function Child() {
this.childname = '子类';
}
// 核心代码:
Child.prototype = new Parent();
缺点
- 父类的引用属性会被所有子类实例共享,就是多个子类实例对父类引用类型的操作会被纂改,无法保持子类实例的个性
- 子类构建实例时不能向父类传递参数
构造函数继承
在子类的构造函数中,执行父类的构造函数,并且为其绑定子类的this.
这是所有继承中唯一一个不涉及到prototype的继承
// 父类
function Parent() {
this.name = ['父类']
this.introduce = function () {
console.log("父类上的introduce方法")
}
}
Parent.prototype.sayhi = function () {
console.log('父类原型上的sayhi方法');
}
// 子类
function Child() {
this.childname = ['子类']
Parent.call(this)
缺点
- 父类的方法不能复用,子类实例的方法每次都是单独创建的
- 继承不到父类原型上的属性和方法
组合继承
构造函数和原型链2中继承组合使用.
// 父类
function Parent() {
this.name = ['父类']
this.introduce = function () {
console.log("父类上的introduce方法")
}
}
Parent.prototype.sayhi = function () {
console.log('父类原型上的sayhi方法');
}
// 子类
function Child() {
this.childname = ['子类']
Parent.call(this) // 第二次调用Parent
}
Child.prototype = new Parent() // 第一次调用Parent
缺点
- 调用了2次父类,原型链和构造函数都调用了父类,从而覆盖了子类上的同名参数,造成性能浪费
原型式继承
利用一个空对象作为中介、将某个对象直接赋值给空对象构造函数的原型,其实就是使用Object.create() ECMAScript 5 通过新增 Object.create()方法规范化了原型式继承。这个方法接收两个参数:一 个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的情况下, Object.create()与 object()方法的行为相同。——《JAVASCript高级编程》
var son=object( Person); var son = Object.create(Person);
缺点:
- 跟原型链继承一样,多个子类实例的引用类型属性指向相同,可能会纂改。
寄生组合式继承
// 父类
function Parent() {
this.name = ['父类']
this.introduce = function () {
console.log("父类上的introduce方法")
}
}
Parent.prototype.sayhi = function () {
console.log('父类原型上的sayhi方法');
}
// 子类
function Child() {
this.childname = ['子类']
Parent.call(this) // 核心代码
}
Child.prototype = Object.create(Parent.prototype) // 核心代码
组合继承有一个会两次调用父类的构造函数造成浪费的缺点,寄生组合继承就可以解决这个问题。
ES6 Class extends
class Parent {}
class Son extends Parent {
constructor() {
super();
}
}
他是一个基于ES6Class和extends的语法糖,实现原理是改变其原型链
class Parent {}
class Son {}
Object.setPrototypeOf = function (obj, proto) {
obj.__proto__ = proto;
return obj;
};
// B 的实例继承 A 的实例
Object.setPrototypeOf(Son.prototype, Parent.prototype);
// B 继承 A 的静态属性
Object.setPrototypeOf(Son, Parent);