欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Javascript继承

程序员文章站 2022-03-04 14:07:39
...

我们用new一个构造函数的方法生成一个实例,比如:

function a() { this.b=2; }

var b = new a()
复制代码

new 这个关键字做了什么?

  • var b = {}
  • b.proto = a.prototype;
  • var res = a.call(b)
  • return typeof res === 'object' ? res : b;

当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object )都有一个私有属性(称之为__proto__)指向它的原型对象(prototype)。给几个例子,B继承自A。

构造函数实现继承

function parent(b) {
  console.log(b);    
  this.name = b;
}

console.log(parent); // 会打印出上述函数

parent.prototype.say = function () {
  console.log('abc');
};

function child (b) {
  parent.call(this, b);
  
  console.log(parent.call(this, b)); // call 会改造this
  
  this.xixi = 2;
}
复制代码

有个缺陷,这个方法不能继承父类的say方法

原型链继承

原型链是 javascript 的典型继承方式, 这种继承方式的最大特点就是共享,所有事例共享原型对象中的所有属性和方法。

function parent(b) {
  this.name = b;
}

parent.prototype.xixi = '123';

function child() {
  this.a=1;
}

child.prototype = new parent(b);
child.prototype.constructor = parent // 保持构造函数和原型对象的完整性

console.log(new child());
复制代码

缺点,new出来的实例通过参数传值赋值的话,一经初始化就永久有个初始值了。所以是无法向父类传参,无法实现多继承的。

组合式继承

简单点来说就是构造函数继承 + 原型链继承,实现了继承,这样父类和子类可以分别拥有自己的实例化属性。

function parent (b) {
  this.name = b;
}

function child (b) {
  parent.call(this, b);
  this.xixi = 1;
}

child.prototype = new parent();
child.prototype.constructor = child;
复制代码

既是子类的实例,也是父类的实例, 但有一个缺点就是调用了两次父类构造函数,造成内存浪费。而且可能发生变量覆盖问题。

寄生组合式继承

改进了一步,使用了Object.create方法,不会造成内存浪费。

function parent (b) {
  this.name = b;
}

function child (b) {
  parent.call(this, b);
  this.xixi = 1;
}

child.prototype = Object.create(parent);
child.prototype.constructor = child;
复制代码

es6 extends

也有寄生组合式继承的优点,通过super来传递父类拿到的参数

class parent {
  constructor(prop) {
    console.log(prop);
  }
}
class child extends parent {
  constructor(prop) {
    super(prop);
    console.log(prop)
  }
}
new child('bb')
复制代码