20200426
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 关键字调用的
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