JS - ES6 的 class

224 阅读3分钟

class 是一种基于原型实现的实现语法糖,为了让面相对象的语法同传统语法一样让程序员更容易接受,让代码更加优雅、可读性更强

class 框架


class ClassName {
  // 类的构造函数,可以传递许多参数,一般在 new 的时候调用一次
  constructor(x, y) {
    // this 是创建的实例,this.attr 是给实例添加 属性
    this.attr = x + y;
  }

  // attr = xx 这样都是将 attr 到当前类的实例(new 后返回的对象)上
  instantanceAttr = 200; // 等价于 this.instantanceAttr = 200,

  // 这个方法是定义在 实例上的
  instanceFn = () => {
    // 箭头函数没有自己的 this, 所用到的 this 是宿主环境的
    console.log(this, " >>>this");
    return this.attr;
  };

  /**
   * 使用 protoFn(){} 是给 当前的类的原型(prototype)上添加 共有的方法,这个是不可枚举的,
   * 但是 实例是可以调用的,因为调用的规则是 先找实例身上有没有,
   * 有就直接调用,没有就去原型上找,一直找到最顶层的原型为止
   */
  protoFn() {
    console.log("Parent.prototype.protoFn");
  }

  /**
   * 使用 static 定义的属性或者方法, 直接使用 类名.属性 或者 类名.方法名() 调用
   */
  static staticVariable = 100; // 这个是静态属性,直接 类名.staticVariable 调用即可

  static staticFn() {
    console.log("这个是静态方法,可以直接通过 类名.staticFn() 直接调用");
  }
}

ClassName.prototype.protoAttr = "123";

// 实例化一个类对象
const instance = new ClassName(2, 3);

console.log("instance: ", instance);

// 调用 instance 上的 方法
instance.instanceFn();

// 获取 instance 上的 属性
console.log("instance.instantanceAttr: ", instance.instantanceAttr);

// 调用 instance 类原型上的 方法
instance.protoFn();

// 获取 instance 类原型上的属性
console.log("instance.protoAttr: ", instance.protoAttr);

// 调用类的静态 方法
ClassName.staticFn();

// 获取 ClassName 类静态的属性
console.log("ClassName.staticVariable: ", ClassName.staticVariable);

class 说明

  • 类是 ES6 的一个语法糖,使得更具传统的面向对象语法、ES5 也是可以做的
  • ES6 类的 prototype 依然存在,prototype 对象的 constructor 属性指向类本身
  • 与 ES5 一样,类的所有实例共享一个原型对象 即
const inst1 = new ClassName(1,2);
const inst2 = new ClassName(2,3);

console.log(Object.getPrototypeOf(inst1) === Object.getPrototypeOf(inst2)); // true

inst1, inst2 都是 ClassName 的实例,他们的原型都是 ClassName.prototype, 因此 __proto__ 属性也是相同的
  • 静态方法不会被继承的
  • super 扮演的角色
    • 在子类的构造函数中指的是父类的构造函数
    • 在子类的普通方法中 super 是父类的原型对象
    • 在子类的静态方法中 super 是父类
class Parent {
  constructor() {
    // 定义在父类的实例属性
    this.pNum = 2;
  }

  // 定义在 Parent.prototype 上的 function
  pFn() {
    console.log("parent normal fn");
  }

  // 定义在 Parent.prototype 上的 function
  pFn2() {
    console.log("parent normal fn2");
  }

  // 静态方法,只能 Parent.pStaticFn() 调用
  static pStaticFn() {
    console.log("parent static fn");
  }
}

class Son extends Parent {
  constructor() {
    // 这里的 super 指的是父类的构造函数
    super();

    // 这里的 super 指的是指向父类的原型对象
    super.pFn();

    // 因为 super 指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过 super 调用的
    console.log("super.pNum: ", super.pNum); // undefined
  }

  sonFn() {
    // 普通方法中的 super 指的是指向父类的原型对象
    super.pFn2();
  }

  static sonStaticFn() {
    // 静态方法中的 super 指的是 父类, 而不是父类的原型对象
    super.pStaticFn();
  }
}

const son = new Son(); // log:  parent normal fn

son.sonFn(); // log: parent normal fn2
Son.sonStaticFn(); // log: parent static fn