iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 10
2
Modern Web

一步一腳印-紮紮實實學es6系列 第 10

ES6 的 Class 、super 的特例與繼承

  • 分享至 

  • xImage
  •  

鐵人第10天了,1/3 加油!
今天國慶日,學習了一下es6的繼承

ES6 中的CLASS 有許多規範
我們在這邊整理一下
下邊會詳細說明,之後如果有再念到多的也會補充在這邊

  • class 中只能放方法(在class 中的function都叫做method)
  • class 雖然長得像物件,但是方法與方法間不可以有逗號
  • 子類別需要在constructor()中呼叫super()來使用父類別的建構函式
  • 冷知識:super() 只能在constructor()中執行
  • 子類別的constructor()呼叫super之前,this是沒有指向的,會跑出Refference Error
  • 可以用get() set() 去存取私有屬性 ,但es6中好像還沒有私有屬性(待確認)

繼承寫法

我們把昨天的範例拿來詳細說明Class 的繼承怎麼寫的
下面再詳細討論super()

class Person{
    constructor(age,weight){
        this.age=age;
        this.weight=weight;
        
    }
    call_this(){
        return this;
    }
    static SonCanNotUse(){
        console.log("老子專用");
		
        
    }
	

}
class SuperMan extends Person{
	constructor(age,weight,power){
    // 如果在super()之前就呼叫this 的話,會refference error
		super();
		this.power=power;		
	}
	hello(){
		console.log(`我是個有${this.power}戰鬥力的SuperMAN`);
	}
}

可以發現到 我們創建了一個類別SuperMan,extends 了Person
這意思是SuperMan 是繼承Person 而來的
並且在建構函式(constructor()) 中呼叫了super()
這邊的super 就是幫我們使用父類別Person()的建構函式
所以雖然我們沒有寫this.age=age ,但卻是可以生效的

而子類這邊的this 是指向實例的,也就是說呢 是指向你new 出來的東東
這個我們昨天有交代過了,再複習一下

super 當做物件使用方法

在子類中,可以用super注意,沒有括號 來呼叫父類別的原型
在子類中呼叫父類別的原型可以做什麼呢?

  • 可以增加屬性/修改屬性
  • 可以呼叫父類別的方法
  • 可以對原類別prototype中的屬性
    相信這些繞口的文言文沒人想看是吧
    讓我們來看看例子!
class Person{
    constructor(age,weight){
        this.age=age;
        this.weight=weight;
        this.property='會在父類別實例中產生的屬性'
    }
    call_this(){
        return this;
    }
    showProperty(){
        console.log(`父類別實例的: ${this.property}`)
    }
    static SonCanNotUse(){
        console.log("老子專用");
        console.log(`父類別私有方法的: ${this.property}`)
		
        
    }
	

}
class SuperMan extends Person{
	constructor(age,weight,power){
    // 如果在super()之前就呼叫this 的話,會refference error
		super();
        this.property="子類用this初始化的property";
        super.property="子類用super初始化的property";
		this.power=power;
        super.showProperty();
	}
	hello(){
		console.log(`子類實例中,被super.property改掉的property${this.property}`);
	}
    static sonPrivateMethod(){
        super.showProperty();
    }
}

接下來我們來new 一個SuperMAN

var kkman=new SuperMan(1,2,3)

會印出什麼呢?
我們會期待在constructor()中執行的函式似乎會起作用
super.showProperty();
這個東西會出什麼哩?!
首先這個super 會指向父類的prototype
那父類的prototype 裡有showProperty這個方法對吧

所以會印出

  1. 會在父類別實例中產生的屬性
  2. 子類用this初始化的property
  3. 子類用super初始化的property

猜猜看!!

好了我想沒人會猜,都馬會直接跑

但是跑程式之前,還是要想一下之後才會有疑問吶!S
結果竟然是...
https://ithelp.ithome.com.tw/upload/images/20181010/20110579HbLGrrKbnh.png

蛤!!!
那這不就代表
在子類別的

this.property="子類用this初始化的property";
super.property="子類用super初始化的property";

這邊的this 跟super 都相等!??

沒那麼容易

同學,他們其實只有在賦值的時候相等歐...

不信你在constructor 裡加入console.log(super.showProperty)試試看...

https://ithelp.ithome.com.tw/upload/images/20181010/201105796q1MH9II56.png
...什麼鬼
undefined!!
對穿腸又嘔出幾兩鮮血

到底在這邊的super 又是等於誰呢??怎麼會undefine??
我們不到黃河心不死,一定要找出目前的super到底代表誰
在賦值的時候 super 等同 子類中的this,指向子類實例
但是在取值的時候,竟然不是??
難道是像剛才呼叫方法的時候,super又指向父類的prototype嗎?
我們趕快來看一下測試結果!!

https://ithelp.ithome.com.tw/upload/images/20181011/20110579z7wRdS71R9.png

果然沒錯!!

所以在子類的constructor()中
用super賦值時的super指向子類實例,等同this
當super取值時,這邊的super指向父類的prototype!
....hen棒...
猜不透你呀


上一篇
ES6 中Class 私有方法與this的探討
下一篇
解構賦值
系列文
一步一腳印-紮紮實實學es630
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
神Q超人
iT邦研究生 5 級 ‧ 2018-10-11 00:57:44

加油!剩下2/3了!
看到這篇想起小弟剛在學物件繼承的時候搞得超混亂/images/emoticon/emoticon70.gif

0
zeze
iT邦新手 2 級 ‧ 2021-10-07 01:37:28

這邊的 super() 裡面不給參數不會壞掉嗎

class SuperMan extends Person{
	constructor(age,weight,power){
    // 如果在super()之前就呼叫this 的話,會refference error
		super();
		this.power=power;		
	}
	hello(){
		console.log(`我是個有${this.power}戰鬥力的SuperMAN`);
	}
}
YUAN iT邦新手 3 級 ‧ 2022-05-23 09:31:25 檢舉

super(age,weight); //應該是這樣
不然會 {age:undefined,weight:undefined}

我要留言

立即登入留言