ES6中的类与继承

本文深入探讨ES6中类和继承的实现机制,对比ES5的继承方式,揭示ES6如何利用class和extends语法糖简化面向对象编程,以及其背后的Object.create()和Object.setPrototypeOf()等方法的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

ES6中通过class实现了类,通过extends实现并标准化了继承,而class、extends本质是语法糖,使用Babel即可将其转为ES5的代码实现。
那么ES6中的类是如何实现的,ES6中继承实现和ES5有什么区别?它又是如何使用ES5实现的继承呢?
首先我们使用Babel,将最简单的ES6类与继承代码转换为ES5,如下:

// ES6代码
class SuperClass {
	constructor() {
		this.value = 1;
	}
  
  	toStringSuper() {}
}

class SubClass extends SuperClass {
	constructor() {
    	super();
      	this.name = 'sub';
    }
}


转换后的ES5代码:

// ES5 代码

'use strict';

var _createClass = (function() {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ('value' in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }
  return function(Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
})();

function _possibleConstructorReturn(self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }
  return call && (typeof call === 'object' || typeof call === 'function') ? call : self;
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== 'function' && superClass !== null) {
    throw new TypeError(
      'Super expression must either be null or a function, not ' + typeof superClass
    );
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: { value: subClass, enumerable: false, writable: true, configurable: true }
  });
  if (superClass)
    Object.setPrototypeOf
      ? Object.setPrototypeOf(subClass, superClass)
      : (subClass.__proto__ = superClass);
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError('Cannot call a class as a function');
  }
}

var SuperClass = (function() {
  function SuperClass() {
    _classCallCheck(this, SuperClass);

    this.value = 1;
  }

  _createClass(SuperClass, [
    {
      key: 'toStringSuper',
      value: function toStringSuper() {}
    }
  ]);

  return SuperClass;
})();

var SubClass = (function(_SuperClass) {
  _inherits(SubClass, _SuperClass);

  function SubClass() {
    _classCallCheck(this, SubClass);

    var _this = _possibleConstructorReturn(
      this,
      (SubClass.__proto__ || Object.getPrototypeOf(SubClass)).call(this)
    );

    _this.name = 'sub';
    return _this;
  }

  return SubClass;
})(SuperClass);


一、类与class语法糖

首先,从class开始,我们先来看SuperClass转化出的代码:

// ES5 代码
'use strict';

var _createClass = (function() {
  function defineProperties(target, props) {
    for (var i = 0; i < props.length; i++) {
      var descriptor = props[i];
      descriptor.enumerable = descriptor.enumerable || false;
      descriptor.configurable = true;
      if ('value' in descriptor) descriptor.writable = true;
      Object.defineProperty(target, descriptor.key, descriptor);
    }
  }
  return function(Constructor, protoProps, staticProps) {
    if (protoProps) defineProperties(Constructor.prototype, protoProps);
    if (staticProps) defineProperties(Constructor, staticProps);
    return Constructor;
  };
})();
function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError('Cannot call a class as a function');
  }
}

var SuperClass = (function() {
  function SuperClass() {
    _classCallCheck(this, SuperClass);

    this.value = 1;
  }

  _createClass(SuperClass, [
    {
      key: 'toStringSuper',
      value: function toStringSuper() {}
    }
  ]);

  return SuperClass;
})();

代码不难理解,主要分为几个部分:

  1. SuperClass后面是一个自执行函数,里面定义了SuperClass构造函数,以及执行了为SuperClass添加属性的_createClass函数
  2. _createClass的功能主要就是使用Object.defineProperty为SuperClass的原型对象添加toStringSuper属性,而且属性的enumerablefalse

二、extends与继承

function _possibleConstructorReturn(self, call) {
  if (!self) {
    throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
  }
  return call && (typeof call === 'object' || typeof call === 'function') ? call : self;
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== 'function' && superClass !== null) {
    throw new TypeError(
      'Super expression must either be null or a function, not ' + typeof superClass
    );
  }
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: { value: subClass, enumerable: false, writable: true, configurable: true }
  });
  if (superClass)
    Object.setPrototypeOf
      ? Object.setPrototypeOf(subClass, superClass)
      : (subClass.__proto__ = superClass);
}

function _classCallCheck(instance, Constructor) {
  if (!(instance instanceof Constructor)) {
    throw new TypeError('Cannot call a class as a function');
  }
}

var SuperClass = (function() {
  function SuperClass() {
    _classCallCheck(this, SuperClass);

    this.value = 1;
  }

  _createClass(SuperClass, [
    {
      key: 'toStringSuper',
      value: function toStringSuper() {}
    }
  ]);

  return SuperClass;
})();

var SubClass = (function(_SuperClass) {
  _inherits(SubClass, _SuperClass);

  function SubClass() {
    _classCallCheck(this, SubClass);

    var _this = _possibleConstructorReturn(
      this,
      (SubClass.__proto__ || Object.getPrototypeOf(SubClass)).call(this)
    );

    _this.name = 'sub';
    return _this;
  }

  return SubClass;
})(SuperClass);

继承的实现主要围绕_inherits函数来执行:

  1. 与ES5中寄生组合式继承不同,ES6中继承使用Object.create()以SuperClass的原型对象创建了一个新的原型对象,即SubClass.prototype.__proto__ = SuperClass.prototype。 同时使其constructor属性指向SubClass。
  2. ES5的继承是子类的原型对象__proto__属性指向父类的原型对象,而ES6中继承是子类__proto__指向父类。

在创建新子类对象时:

  1. 通过(SubClass.__proto__ || Object.getPrototypeOf(SubClass)).call(this)此处的代码执行了父类的构造函数,即:SubClass.__proto__.call(this)等于SuerClass.call(this)
  2. 得到_this后,再使用子类的constructor中的内容来修改_this,最后返回。
  3. 如果以ES5的继承方式,使用的是SuperClass.apply(this)的方式来执行,而ES6是返回新的_this后再修改,这是两者的不同之处。的是SuperClass.apply(this)的方式来执行,而ES6是返回新的_this后再修改,这是两者的不同之处。

最后形成的结构图如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值