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

有关JavaScript继承的几种写法

程序员文章站 2022-04-11 12:50:34
...

一、通过构造函数实现继承

  function Parent() {
      this.name = 'name';
    }
    Parent.prototype.say = function () {
      console.log('say');
    }
    function Child() {
      Parent.call(this);
      this.type = 'child';
    }
    const child = new Child();
    ```


这种方式通过在子类的构造函数中调用父构造函数实现继承,但是有个致命的缺点:如下图,子类实例并不能继承父类中原型对象上的属性或者方法。

这里写图片描述


##   二、通过原型对象实现继承

```js
    function Parent() {
      this.name = 'name';
      this.favor = ['blue', 'red'];
    }
    Parent.prototype.say = function () {
      console.log('say');
    }
    function Child() {
      this.type = 'child';
    }
    Child.prototype = new Parent();
    const child = new Child();

这种方式通过给子类构造函数的prototype对象赋值实现继承,如下图,无论是name属性还是say方法都能被子类实例访问到。
这里写图片描述
但是这种方式也有缺点,如下图,当父类的属性是引用类型时,子类实例继承的是同一份属性,任一实例改变该属性都会引起全局变化,无法互相隔离。
这里写图片描述

三、组合方式

    function Parent() {
      this.name = 'name';
      this.favor = ['blue', 'red'];
    }
    Parent.prototype.say = function () {
      console.log('say');
    }
    function Child() {
      Parent.call(this);
      this.type = 'child';
    }
    Child.prototype = new Parent();
    const child = new Child();

结合了上两种方式,避免了上面的缺点。但是这种方式在每次实例化子类实例时,都会调用两次父类构造函数,需要优化。

四、组合优化①

  function Parent() {
      this.name = 'name';
      this.favor = ['blue', 'red'];
    }
    Parent.prototype.say = function () {
      console.log('say');
    }
    function Child() {
      Parent.call(this);
      this.type = 'child';
    }
    Child.prototype = Parent.prototype;
    const child = new Child();

在给子类prototype赋值时不要采用实例化父类的方式,直接赋值父类的prototype。

其实,这种方式也有缺点:如下图,子类实例的constructor属性直接指向了父类构造函数,导致无法判断当前对象实例化自哪个构造函数。

这里写图片描述

五、组合优化②

    function Parent() {
      this.name = 'name';
      this.favor = ['blue', 'red'];
    }
    Parent.prototype.say = function () {
      console.log('say');
    }
    function Child() {
      Parent.call(this);
      this.type = 'child';
    }
    Child.prototype = Object.create(Parent.prototype);
    Child.prototype.constructor = Child;
    const child = new Child();

终极改造完成:通过Object.create()方法指定了子类实例的__proto__属性,同时显式声明子类的constructor。

2019-06-04,先记到这里,后续还有补充。。。