# 实现class与extends

为了与其它语言在实现类上,写法一致。ES6加入了class关键字,方便开发者创建类。

但JS原生并没有类这个东西,为了实现类的效果,其本质是通过JS的构造器实现。

class使用new关键字生成实例,而构造器也是通过new来实例化,因此也可以推断class本质就是构造器的语法糖。

# 手动实现class

const Class = (function () {
  function Constructor(name) {
    this.name = name;
  }
  // 添加原型方法
  Constructor.prototype.getName = function getName() {
    console.log('原型方法getName:' + this.name);
  }
  // 添加原型属性
  Constructor.prototype.age = '原型属性age';
  // 添加静态方法
  Constructor.log = function log() {
    console.log('我是构造器的静态方法log');
  }
  // 添加静态属性
  Constructor.isWho = '构造器静态属性isWho';
  return Constructor;
})();
const obj = new Class('我是实例');

实现class语法糖,只需封装一层函数。

  • 返回的Constructor就是实例的构造器,其prototype是个空白的对象。
  • new调用的函数必须是一个构造器函数,用于构造实例,此构造器的this指向实例。
  • 构造器内部需要实现依照传入的参数设置实例的属性。
  • 定义class时需要实现原型属性和静态属性的挂载。

以上只实现class的定义,接下来还要实现继承。

# 实现extends

  • 继承需要满足原型的继承
  • 继承还需要能够调用父类构造器
// 父类
const Parent = (function () {
  function Constructor(age) {
    this.age = age
  }
  Constructor.prototype.getName = function () {
    console.log(this.name);
  }
  return Constructor;
})();
// 子类
const Child = (function (_Parent = null) {
  if (_Parent) {
    Constructor.prototype = Object.create(_Parent.prototype, {
      constructor: {
        value: Constructor,
        enumerable: false,
        writable: true,
        configurable: true
      }
    });
    Constructor.__proto__ = _Parent;
  }
  function Constructor(name, age) {
    _Parent ? _Parent.call(this, age) : this;
    this.name = name;
  }
  Constructor.prototype.getAge = function () {
    console.log(this.age);
  };
  return Constructor;
})(Parent);
  • 实现原型继承,可以使用之前的继承写法,注意class形式的继承,会把父类设为子类的__proto__
  • 在构造函数内判断是否有父类,如果有就要调用父类的构造函数,把当前的this传入,这样才能生成父类构造器中定义的属性,这才算是真正的继承。继承不单继承原型,还能继承父类构造器中定义的属性
  • 对于原型方法和静态方法也是类似定义,注意定义的方法,如果用到this需要使用function关键字定义函数,不可使用匿名函数,否则this无法指向调用对象本身
最近更新时间: 2020/5/26 19:03:58