20200426

@xiaojingzhao

Plan

  • 你不知道的 js -- 代码组织

Notes

模块加载

  • super 是静态绑定到类上的
class ParentA {
  constructor() {
    this.id = "a";
  }
  foo() {
    console.log("ParentA: ", this.id);
  }
}
class ParentB {
  constructor() {
    this.id = "b";
  }
  foo() {
    console.log("ParentB: ", this.id);
  }
}
class ChildA extends ParentA {
  foo() {
    super.foo();
    console.log("ChildA: ", this.id);
  }
}
class ChildB extends ParentB {
  foo() {
    super.foo();
    console.log("ChildA: ", this.id);
  }
}

var a = new ChildA();
a.foo();

var b = new ChildB();
b.foo();

输出:

// ParentA: a;
// ChildA: a;
// ParentB: b;
// ChildB: b;

静态绑定:

b.foo.call(a);
// 输出
// ParentB: a;
// ChildB: a;

这里可以看到,通过 super 调用的 foo 还是指向的 ParentB,但是 this 已经被动态绑定到 a 上了。

去运行一下这个demo

  • 子类构造器中调用 super(...) 之后才能访问 this
class Sub extends Sup {
  constructor() {
    this.a = "a"; // 错误
    super();
  }
}

new.target

  • 元属性(meta property)

new.target 总是指向 new 实际上直接调用的构造器,即使构造器是在父类中且通过子类构造器用 super(...)委托调用

class Foo {
  constructor() {
    console.log("Foo: ", new.target.name);
  }
}

class Bar extends Foo {
  constructor() {
    super();
    console.log("Bar: ", new.target.name);
  }

  baz() {
    console.log("baz: ", new.target);
  }
}

let a = new Foo(); // Foo: Foo
let b = new Bar(); // Foo: Bar; Bar: Bar
b.baz(); // undefined -- 不是通过 new 关键字调用的

demo

static

Symbol species Getter

父类方法需要构建新实例,但不想使用子类构造器时, Symbol species Getter 可以指定构造器

class Foo {
  static get [Symbol.species]() {
    return this;
  }

  spawn() {
    return new this.constructor[Symbol.species](); // 子类通知
  }
}

class Bar extends Foo {
  static get [Symbol.species]() {
    return Foo;
  }
}

var a = new Foo();
var b = a.spawn();

var x = new Bar();
var y = x.spawn(); // 子类通知了父类使用哪个构造器

console.log("a instance Foo", a instanceof Foo); // true
console.log("b instance Foo", b instanceof Foo); // true
console.log("x instance Foo", x instanceof Foo); // true
console.log("x instance Bar", x instanceof Bar); // true
console.log("y instance Bar", y instanceof Bar); // false
console.log("y instance Foo", y instanceof Foo); // true

More