babel中的extends

317 阅读1分钟
class Person {
  constructor(name) {
    this.name = name
  }
  sayHi() {
    console.log('sayhi')
  }
}

class Student extends Person {
  constructor(props) {
    super(props)
  }
  sayHi() {
    console.log(`I'm ${ this.name }, and I'm a student`)
  }
}


// 不调用super的报错
function _assertThisInitialized(self) {
    if (self === void 0) {
        throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); 
     } return self;
}



var Person = function () {
  function Person(name) {
    _classCallCheck(this, Person);
    this.name = name;
  }
  _createClass(Person, [{
    key: "sayHi",
    value: function sayHi() {
      console.log('sayhi');
    }
  }]);
  return Person;
}();

var Student = function (_Person) {
  // 必须在_createClass之前执行,这里会覆盖掉Student.prototype上的行为
  _inherits(Student, _Person); 
  var _super = _createSuper(Student);
  // 调用super
  function Student(props) {
    _classCallCheck(this, Student);
    return _super.call(this, props);
  }
  // 不调用super
  // function Student(props) {
  //   var _this;
  //   _classCallCheck(this, Student);
  //   return _possibleConstructorReturn(_this);
  // }

  _createClass(Student, [{
    key: "sayHi",
    value: function sayHi() {
      console.log(`I'm ${ this.name }, and I'm a student`);
    }
  }]);

  return Student;
}(Person);

// Object.getPrototypeOf的兼容
function _getPrototypeOf(o) {
  _getPrototypeOf =
    Object.setPrototypeOf
      ? Object.getPrototypeOf
      : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o);
}

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

function _isNativeReflectConstruct() {
  if (typeof Reflect === "undefined" || !Reflect.construct) return false;
  if (Reflect.construct.sham) return false;
  if (typeof Proxy === "function") return true;
  try {
    // 能力检测  验证Reflect.construct存在
    Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () { }));
    return true;
  } catch (e) { return false; }
}

function _possibleConstructorReturn(self, call) {
  if (call && (typeof call === "object" || typeof call === "function")) {
    return call;
  } return _assertThisInitialized(self);
}

function _createSuper(Derived) {
  var hasNativeReflectConstruct = _isNativeReflectConstruct();
  return function _createSuperInternal() {
    // Student.__proto__ ---> Person
    // 在 _inherit 内部有将 _setPrototypeOf(Student, Person)
    var Super = _getPrototypeOf(Derived), result;
    if (hasNativeReflectConstruct) {
      // 这个this指Student的实例,所以指向 Student.prototype
      // 构造函数即为 Student.prototype.constuctor
      var NewTarget = _getPrototypeOf(this).constructor;
      result = Reflect.construct(Super, arguments, NewTarget);
    } else {
      // 继承静态属性,Person改造之后一定会返回Person的
      result = Super.apply(this, arguments);
    }
    return _possibleConstructorReturn(this, result);
  };
}

function _inherits(subClass, superClass) {
  if (typeof superClass !== "function" && superClass !== null) {
    throw new TypeError("Super expression must either be null or a function");
  }
  // 以superClass的原型创建一个对象,同时修改这个对象的构造函数为subClass
  subClass.prototype = Object.create(superClass && superClass.prototype, {
    constructor: {
      value: subClass,
      writable: true,
      configurable: true
    }
  });

  // subClass.__proto__ = superClass
  // 单独看这里觉得很奇怪  需要配合_createSuper看
  if (superClass) _setPrototypeOf(subClass, superClass);
}


// 是否用做构造函数
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

// 往构造函数的原型上添加属性
// Person.prototype.sayHi = function() {}
function _createClass(Constructor, protoProps, staticProps) {
    if (protoProps) _defineProperties(Constructor.prototype, protoProps); 
    if (staticProps) _defineProperties(Constructor, staticProps); 
    return Constructor; 
}

// 复制props到target上
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);
  }
}

总计一下:

继承的实现步骤:

  • 1、基于需要继承的构造器,改写目标构造器的原型,需要注意的是修改修改原型的constuctor为目标构造函数(_inherits方法)
  • 2、添加父构造器的静态方法(_createSuper
  • 3、添加自身的原型方法(_createClass