目錄

JS 繼承(1): class property跑去哪了?

探討 JS 繼承的 class property 行為

Class A extends Component

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
class A extends Component {
  static color = "red";
  counter = 0;

  arrowOnClick = () => {
    console.log("A arrowOnClick");
  }
  
  onClick(){
    console.log("A onClick");
  }
}

經由 Babel 轉譯後,class properties 都會被移到 constructor 內

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
/* --- After Babel --- */
class A {
  constructor() {
    // class properties 都會被移到 constructor 內
    this.counter = 0;
    this.arrowOnClick = () => {};
  } 
  onClick() {}
}
A.color = "red";

console.log(A.prototype); 
// Console output: {constructor: ƒ, onClick: ƒ}
// 因尚未實例化,因為沒跑constructor,所以看不到 class properties !

多重繼承

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
class B extends A {
  arrowOnClick = () => {
    super.arrowOnClick(); // error occurred !!
    console.log("B arrowOnClick");
  }
  
  onClick(){
    super.onClick();
    console.log("B onClick");
  }
}

console.log(B.prototype); //B extends A, we get prototype of a
// A {constructor: ƒ, onClick: ƒ}

console.log(B.prototype.__proto__);
// {constructor: ƒ, onClick: ƒ}

new B().arrowOnClick(); //error occurred!
new B().onClick();
/*
--- console output ---
A onClick (from line 8)
B onClick (from line 9)
*/


class C extends A {
  arrowOnClick() { // never called!
    super.onClick(); 
    console.log("C onClick");
  }
}

console.log(C.prototype);
// A {constructor: ƒ, arrowOnClick: ƒ}

console.log(C.prototype.__proto__);
// {constructor: ƒ, onClick: ƒ}

new C().arrowOnClick(); //'new C()' 會執行 A 的 constructor !
// A arrowOnClick


class D extends A {} 
new D().arrowOnClick();
// A arrowOnClick

記錄一下。