js中的super小結

邵天宇Soy發表於2019-04-30

1.this和super的區別:

  • this關鍵詞指向函式所在的當前物件
  • super指向的是當前物件的原型物件

2.super的簡單應用

const person = {
	name:'jack'
}

const man = {
	sayName(){
		return super.name;
	}
}

Object.setPrototypeOf( man, person );

let n = man.sayName();

console.log( n )	//jack
複製程式碼

3.super的另類實現

super.name  
等同於   
Object.getPrototypeOf(this).name【屬性】  
等同於   
Object.getPrototypeOf(this).name.call(this)【方法】
複製程式碼

4.super中的this指向(易混淆)

super.name指向的是原型物件person 中的name,但是繫結的this還是當前的man物件。

const person = {
	age:'20多了',
	name(){
		return this.age;
	}
}

const man = {
	age:'18歲了',
	sayName(){
		return super.name();
	}
}

Object.setPrototypeOf( man, person );

let n = man.sayName();

console.log( n )	//18歲了

複製程式碼

Object.getPrototypeOf(this).name指向的是person的name,繫結的this也是person

const person = {
	age:'20多了',
	name(){
		return this.age;
	}
}

const man = {
	age:'18歲了',
	sayName(){
		return Object.getPrototypeOf(this).name();
	}
}

Object.setPrototypeOf( man, person );

let n = man.sayName();

console.log( n )		//20多了
複製程式碼

Object.getPrototypeOf(this).name.call(this)指向的是person的name,不過通過call改變了函式的執行上下文,所以this指向的還是man

const person = {
	age:'20多了',
	name(){
		return this.age;
	}
}

const man = {
	age:'18歲了',
	sayName(){
		return Object.getPrototypeOf(this).name.call(this)
	}
}

Object.setPrototypeOf( man, person );

let n = man.sayName();

console.log( n )	//18歲了

複製程式碼

4.Class中的super

(1)Class中的 super(),它在這裡表示父類的建構函式,用來新建父類的 this 物件

super()相當於Parent.prototype.constructor.call(this)

 class Demo{
			 
	 constructor(x,y) {
	     this.x = x;
		 this.y = y;
	 }
	 
	 customSplit(){
		 return [...this.y]
	 }
	 
 }
 
 class Demo2 extends Demo{
	 constructor(x,y){
		 super(x,y);
	 }
	 
	 customSplit(){
	 	return [...this.x]
	 }
	 
	 task1(){
		 return super.customSplit();
	 }
	 
	 task2(){
	 	return this.customSplit();
	 }
 }
 
 let d = new Demo2('hello','world');
 d.task1()	//["w", "o", "r", "l", "d"]
 d.task2()	//["h", "e", "l", "l", "o"]
複製程式碼

(2)子類沒有自己的this物件,而是繼承父親的this物件,然後進行加工。如果不呼叫super,子類就得不到this物件

class Demo2 extends Demo{
	constructor(x,y){
		 this.x = x;		//this is not defined
	 }
 }
複製程式碼

ES5的繼承,實質上是先創造子類的例項物件this,然後再將父類的方法新增到this上(Parent.call(this)). ES6的繼承,需要先建立父類的this,子類呼叫super繼承父類的this物件,然後再加工。

如果子類沒有建立constructor,這個方法會被預設新增:

class Demo{ 
	 constructor(x) {
	   this.x = x;
	 }
}

class Demo2 extends Demo{}

let d = new Demo2('hello');

d.x 		//hello
複製程式碼

(3) super 在靜態方法之中指向父類,在普通方法之中指向父類的原型物件

class Parent {
	static myMethod(msg) {
		console.log('static', msg);
	}
	myMethod(msg) {
		console.log('instance', msg);
	}
}
class Child extends Parent {
	static myMethod(msg) {
		super.myMethod(msg);
	}
	myMethod(msg) {
		super.myMethod(msg);
	}
}

Child.myMethod(1); // static 1

var child = new Child();
child.myMethod(2); // instance 2
複製程式碼

相關文章