ES6 Class 的代码转换与实现继承的源码

272 阅读2分钟

(Class)代码经过babel 编译后结构会发生改变

class Animal {

  constructor(name) {
    this.speed = 0;
    this.name = name;
  }

  run(speed) {
    this.speed += speed;
    alert(`${this.name} runs with speed ${this.speed}.`);
  }

  stop() {
    this.speed = 0;
    alert(`${this.name} stopped.`);
  }

}


// Inherit from Animal
class Rabbit extends Animal {
  hide() {
    alert(`${this.name} hides!`);
  }
}
var a = new Rabbit('123');
a.hide();

经过编译后的 Class 结构

var Animal = /*#__PURE__*/function () {
  "use strict";

  function Animal(name) {
    _classCallCheck(this, Animal);

    this.speed = 0;
    this.name = name;
  }

  _createClass(Animal, [{
    key: "run",
    value: function run(speed) {
      this.speed += speed;
      alert("".concat(this.name, " runs with speed ").concat(this.speed, "."));
    }
  }, {
    key: "stop",
    value: function stop() {
      this.speed = 0;
      alert("".concat(this.name, " stopped."));
    }
  }]);

  return Animal;
}(); // Inherit from Animal


var Rabbit = /*#__PURE__*/function (_Animal) {
  "use strict";

  _inherits(Rabbit, _Animal);

  var _super = _createSuper(Rabbit);

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

    return _super.apply(this, arguments);
  }

  _createClass(Rabbit, [{
    key: "hide",
    value: function hide() {
      alert("".concat(this.name, " hides!"));
    }
  }]);

  return Rabbit;
}(Animal);

var a = new Rabbit('123');
a.hide();

实现继承的源码

/**
 * 
 * @param {Function} o 传入一个函数
 * @returns {Function|Object} 返回 o 的 __proto__ 父原型链
 */
function _getPrototypeOf(o) {
  _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) {
    return o.__proto__ || Object.getPrototypeOf(o);
  };
  return _getPrototypeOf(o);
}
/**
 * 设置(o的__proto__)的执向到(p)
 * @param {*} o 
 * @param {*} p 
 * @returns {Function} o
 */


function _setPrototypeOf(o, p) {
  _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) {
    o.__proto__ = p;
    return o;
  };

  return _setPrototypeOf(o, p);
}
/**
 * 重写原型subClass的 constructor,设置 (subClass)的__proto__的执向到(superClass)
 * @param {Function} subClass 
 * @param {Function} superClass 
 */


function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }

  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      writable: true,
      configurable: true
    }
  });
  if (superClass) _setPrototypeOf(subClass, superClass);
}
/**
 * 创建继承的父级
 * @param {Function} Derived 传入子函数
 * @returns {Function} 返回 Derived.__proto__ 原型元素
 */


function _createSuper(Derived) {
  return function _createSuperInternal() {
    var Super = _getPrototypeOf(Derived),
        result;

    result = Super.apply(this, arguments);
    return result;
  };
}
/**
 * 设置(Class)属性
 * @param {Function} target 
 * @param {Array} props 
 */


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);
  }
}
/**
 * 
 * @param {Function} Constructor 
 * @param {Array} protoProps 
 * @param {Array} staticProps 
 * @returns {Function} Constructor
 */


function _createClass(Constructor, protoProps, staticProps) {
  if (protoProps) _defineProperties(Constructor.prototype, protoProps);
  if (staticProps) _defineProperties(Constructor, staticProps);
  return Constructor;
}

var Animal = /*#__PURE__*/function () {
  "use strict";

  function Animal(name) {
    this.speed = 0;
    this.name = name;
  }

  _createClass(Animal, [{
    key: "run",
    value: function run(speed) {
      this.speed += speed;
      alert("".concat(this.name, " runs with speed ").concat(this.speed, "."));
    }
  }, {
    key: "stop",
    value: function stop() {
      this.speed = 0;
      alert("".concat(this.name, " stopped."));
    }
  }]);

  return Animal;
}(); // Inherit from Animal


var Rabbit = /*#__PURE__*/function (_Animal) {
  "use strict";

  _inherits(Rabbit, _Animal);

  var _super = _createSuper(Rabbit);

  function Rabbit() {
    var result = _super.apply(this, arguments);

    return result;
  }

  _createClass(Rabbit, [{
    key: "hide",
    value: function hide() {
      alert("".concat(this.name, " hides!"));
    }
  }]);

  return Rabbit;
}(Animal); // console.dir(Rabbit);
// console.log(Rabbit.__proto__);


var a = new Rabbit('4444');
console.dir(a);

总结大概思路

  1. 重写原型 prototype和构造器 constructor,设置__proto__的执向到父级

  2. 重写原型 prototype 和构造器 constructor 后原有的child方法丢失,重新赋值上去。

  3. 父级的私有数据通过利用 Super.apply(this, arguments);拷贝过来,最后返回。