在上一篇文章里介紹了繼承监透,那其中說過一個很關(guān)鍵的東西想要繼承子類里里必需先調(diào)用一個super
方法犀概。而super
的作用絕對是價值連城!同時super
的作用還有多種煮仇,并且跟你的使用環(huán)境有關(guān)系嫉髓。
1观腊、當(dāng)作函數(shù)使用
super
被當(dāng)作函數(shù)使用,這種情況是最普遍的算行,上一篇文章里已經(jīng)使用過梧油。它有以下幾種作用:
- super作為函數(shù)調(diào)用時,代表父類的構(gòu)造函數(shù)
- 調(diào)用super后州邢,this會被改成子類
- 只能用在構(gòu)造函數(shù)里儡陨,用在其它地方報錯
{
class Father{
constructor(){
console.log(new.target.name);
}
}
class Son extends Father{
constructor(){
super();
this.a=10; //這里的this指向,Son的實例
}
method(){
//super() 報錯,只能用在constructor里
}
}
new Father(); //Father(new.target返回Father類)
new Son(); //Son(new.target返回Son子類)
console.log(new Son().a); //10 this指向被修改成了子類的實例
}
子類里面并沒有寫console.log
迄委,但是發(fā)現(xiàn)生成子類實例后褐筛,控制臺里有輸出类少。說明:super
其實相當(dāng)于執(zhí)行了父級的constructor
方法叙身。同時彈出的結(jié)果是指向了子類,又說明雖然調(diào)用的是父類的構(gòu)造函數(shù)硫狞,但是調(diào)用完后會指向子類信轿,this
指向也被改成了子類的實例。其實supe
的作用相當(dāng)于執(zhí)行Father.prototype.constructor.call(this)
;
2残吩、當(dāng)作對象使用
super
也可以被當(dāng)作對象使用财忽,被當(dāng)作對象使用的時候情況有些復(fù)雜,跟上面是完全不一樣的泣侮,同時又按使用環(huán)境分為了兩種情況即彪。
- 在普通方法中,指向父類的原型對象
* 只能調(diào)用原型里的東西
* 如果調(diào)用的是方法活尊,那方法內(nèi)部this指向子類實例
* 如果用super去添加屬性的話隶校,super就是this(實例)
- 在私有方法中,指向父類蛹锰,而不是父類的原型
* 如果調(diào)用的是方法深胳,那方法內(nèi)部this指向子類而不是子類實例
在普通方法中使用
此時切記用super去獲取跟設(shè)置時的指向完全不一樣
{
class Father{
constructor(){
this.a='父類實例的a';
this.b='父類實例的b';
}
showB(){
console.log(`這是父類身上的共享方法,并且會彈出${this.b}`);
}
static showB(){ //私有方法可以與上面的方法重名
console.log(`這是父類身上的私有方法,并且會彈出${this.b}`);
}
}
Father.prototype.a='父類原型的a'; //在原型身上的添加一個屬性a
class Son extends Father{
constructor(){
super(); //這里的super是個方法,作用為引入父類的構(gòu)造函數(shù)(當(dāng)作函數(shù)使用)
this.b='子類實例的b';
//此處聲明:請按注釋標(biāo)的序號順序執(zhí)行代碼
//
/*
* 3铜犬、super設(shè)置屬性
* 1舞终、用super設(shè)置屬性的話,super就代表當(dāng)前環(huán)境的this癣猾。而當(dāng)前環(huán)境為子類的constructor敛劝,所以此時的super代表的就是子類的實例對象
* 2、此時下面的showB()方法彈出的內(nèi)容為"這是父類身上的共享方法,并且會彈出super就是this"是因為纷宇,如果super為this的話攘蔽,那就與上面那段代碼重復(fù)了,后面覆蓋前面
*
*/
super.b='super就是this';
/*
* 4呐粘、super獲取屬性
* 1满俗、此時super的作用是獲取屬性,它依然指向父類的原型對象所以下面這句話相當(dāng)于console.log(Father.prototype.b);所以結(jié)果為undefined作岖。雖然在上面定義了super.b那也不會改變super的指向
*/
console.log(super.b); //undefined
/*
* 1唆垃、這里的super是一個對象,因為constructor是個普通對象
* 1痘儡、super指向父類的原型對象辕万,調(diào)用的是Father的共享方法showB()
* 2、showB方法里的this指向子類的實例,取的是Father的constructor里定義的b
*/
super.showB(); //這是父類身上的共享方法,并且會彈出子類實例的b
//2渐尿、super獲取屬性
console.log(super.a); //父類原型的a 再次驗證只能調(diào)用原型上的東西醉途。原型上與constructor里都有個a,但是調(diào)的是原型上的
}
}
Son.b='子類的私有屬性b';
new Son();
}
在私有方法中使用
此時切記用super的用法與在普通方法中的用法完全相反
{
class Father{
constructor(){
this.b='父類實例的b';
}
showB(){
console.log(`這是父類身上的共享方法,并且會彈出${this.b}`);
}
static showB(){ //這是個私有方法砖茸,與上面的方法重名是可以的
console.log(`這是父類身上的私有方法,并且會彈出${this.b}`);
}
}
Father.prototype.b='父類原型的b'; //在原型身上的添加一個屬性b
class Son extends Father{
constructor(){
super();
this.b='子類實例的b';
}
/*
* 1隘擎、這里的super是在私有方法里調(diào)用,所以指向父類凉夯,調(diào)用的是Father里定義的static showB方法
* 2货葬、此方法里的this指向被改成了子類,彈出的b是子類的私有屬性b
*/
static log(){
super.showB();
}
}
Son.b='子類的私有屬性b';
Son.log(); //這是子類身上的私有方法,并且會彈出子類的私有屬性b
}
忠告:要明確指定supe的類型
super在用的時候必需指定它的類型劲够,不然不清不楚的去用震桶,瀏覽器會給你報錯!
{
class Father{};
class Son extends Father{
constructor(){
super(); //這個是作為函數(shù)
//console.log(super); //報錯 那這個super它是個什么呢征绎?它自己矛盾了蹲姐,瀏覽器迷茫了~
console.log(super.a); //這個是作為對象
}
}
}