ES6的 super 关键字
Class之間可以通過extends關鍵字實現繼承,這比ES5的通過修改原型鏈實現繼承,要清晰和方便很多。
子類必須在constructor方法中調用super方法,否則新建實例時會報錯。
這是因為子類沒有自己的this對象,而是繼承父類的this對象,然后對其進行加工。如果不調用super方法,子類就得不到this對象。ES5的繼承,實質是先創造子類的實例對象this,然后再將父類的方法添加到this上面(Parent.apply(this))。ES6的繼承機制完全不同,實質是先創造父類的實例對象this(所以必須先調用super方法),然后再用子類的構造函數修改this。
在子類的構造函數中,只有調用super之后,才可以使用this關鍵字,否則會報錯。這是因為子類實例的構建,是基于對父類實例加工,只有super方法才能返回父類實例。
類的prototype屬性和proto屬性
大多數瀏覽器的ES5實現之中,每一個對象都有proto屬性,指向對應的構造函數的prototype屬性。Class作為構造函數的語法糖,同時有prototype屬性和proto屬性,因此同時存在兩條繼承鏈。
1)子類的proto屬性,表示構造函數的繼承,總是指向父類。
2)子類prototype屬性的proto屬性,表示方法的繼承,總是指向父類的prototype屬性。
Object.getPrototypeOf()
Object.getPrototypeOf方法可以用來從子類上獲取父類。可以使用這個方法判斷,一個類是否繼承了另一個類。
Class的取值函數(getter)和存值函數(setter)
與ES5一樣,在Class內部可以使用get和set關鍵字,對某個屬性設置存值函數和取值函數,攔截該屬性的存取行為。
Class不存在變量提升(hoist),這一點與ES5完全不同。
Class立即執行表達式
采用Class表達式,可以寫出立即執行的Class。
let person = new class {constructor(name) {this.name = name; //類的方法內部如果含有this,它默認指向類的實例}sayName() {console.log(this.name);} }('張三'); person.sayName(); // "張三" 復制代碼super關鍵字:
super這個關鍵字,既可以當作函數使用,也可以當作對象使用。在這兩種情況下,它的用法完全不同。
1) super作為函數調用時,代表父類的構造函數。ES6 要求,子類的構造函數必須執行一次super函數。
注意,super雖然代表了父類A的構造函數,但是返回的是子類B的實例,即super內部的this指的是B,因此super()在這里相當于
A.prototype.constructor.call(this)。2) super作為對象時,在普通方法中,指向父類的原型對象;在靜態方法中,指向父類。
class A {p() {return 2;} } class B extends A {constructor() {super();console.log(super.p()); // 2//super.p() 相當于 A.prototype.p()} } let b = new B();復制代碼由于super指向父類的原型對象,所以定義在父類實例上的方法或屬性,是無法通過super調用的。
如果屬性定義在父類的原型對象上,super就可以取到。
ES6 規定,通過super調用父類的方法時,super會綁定子類的this。
class A {constructor() {this.x = 1;}print() {console.log(this.x);} } class B extends A {constructor() {super();this.x = 2;}m() {super.print();} } let b = new B(); b.m() // 2復制代碼上面代碼中,super.print()雖然調用的是A.prototype.print(),但是A.prototype.print()會綁定子類B的this,導致輸出的是2,而不是1。也就是說,實際上執行的是super.print.call(this)。
總結
以上是生活随笔為你收集整理的ES6的 super 关键字的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [转]LIB和DLL的区别与使用
- 下一篇: Spring Boot中验证码实现kap