天天看點

自我學習之es6(6)

es6的新特性裡增加了類和類的繼承,其實這個特性也是向背景語言借鑒過來的,先來看下es5的時候如何構造一個對象

function Human(){
  this.eyes=2;
  this.hands=2;
}

Human.prototype.singing=function(){
	console.log('I can sing');
}

let a = new Human();
console.log(a);

a.singing();
           

如上,用es5的方法構造了一個叫Human的對象,在對象裡建立了2個屬性,并用prototype的方法挂載了一個方法,申明了一個a為Human對象的執行個體化,并用這個a調用singing這個方法

再來看,如何用es6來申明一個類:

class Human{
	constructor(){
		this.eyes=2;
		this.hands=2;
	}
}

let a = new Human();
console.log(a);
           

es6用class關鍵字來申明一個類,并用constructor來建立一個類的構造函數,初始化一個對象的屬性,其實es6隻是用了一種更語義化、更規範的方式去申明一個類,但是其背後的原理還是基于es5的,如果要建立一個方法,也無需再挂載到原型上 直接在對象裡建立

class Human{
	constructor(){
		this.eyes=2;
		this.hands=2;
	}

	singing(){
		console.log('I can sing');
	}
}

let a = new Human();
console.log(a);

a.singing();
           

es6裡是如何繼承類的呢

class Human{
	constructor(){
		this.eyes=2;
		this.hands=2;
	}

	singing(){
		console.log('I can sing');
	}
}

let a = new Human();
console.log(a);

a.singing();

class NormalMan extends Human {

}

let b=new NormalMan();
console.log(b);
           

類可以繼承另外一個類,使用extends文法,可以繼承到另外一個類的所有屬性和方法,除此之外,它也可以改造繼承過來的屬性和方法或者建立新的屬性和方法

class Human{
	constructor(){
		this.eyes=2;
		this.hands=2;
	}

	singing(){
		console.log('I can sing');
	}
}

let a = new Human();
console.log(a);

a.singing();

class NormalMan extends Human {
  	constructor(){
  		super();
		this.eyes=100;
		this.hands=200;
		this.feet=2;
	}

	singing(){
		console.log('NormalMan can sing');
	}
	run(){
		console.log('NormalMan can run');
	}
}

let b=new NormalMan();
console.log(b);
b.singing();
b.run();
           

可以在constructor裡改造繼承過來的屬性,還可以建立自己的方法,super()調用了一下父類的構造函數,當繼承了另外一個類的時候就必須使用,如果不用就會報錯。

我們可以在父類的構造函數裡傳參,在調用的時候傳參

class Human{
	constructor(eyes=2,hands=2){
		this.eyes=eyes;
		this.hands=hands;
	}

	singing(){
		console.log('I can sing');
	}
}

let a = new Human(3,4);
console.log(a);

a.singing();

class NormalMan extends Human {
  	constructor(){
  		super();
		this.eyes=100;
		this.hands=200;
		this.feet=2;
	}

	singing(){
		console.log('NormalMan can sing');
	}
	run(){
		console.log('NormalMan can run');
	}
}

let b=new NormalMan();
console.log(b);
b.singing();
b.run();
           

super()裡調用的是父類的構造函數,是以super()裡也可以傳參

class Human{
	constructor(eyes=2,hands=2){
		this.eyes=eyes;
		this.hands=hands;
	}

	singing(){
		console.log('I can sing');
	}
}

let a = new Human(3,4);
console.log(a);

a.singing();

class NormalMan extends Human {
  	constructor(){
  		super(1000,2000);
		this.feet=2;

	}

	singing(){
		console.log('NormalMan can sing');
	}
	run(){
		console.log('NormalMan can run');
	}
}

let b=new NormalMan();
console.log(b);
b.singing();
b.run();
           

關于構造函數裡的this指向,我們可以在繼承的函數的構造函數裡面傳一個name的參數,并在構造函數裡建立一個name的屬性,在singing()的方法裡可以用模闆字元串${this.name}去拼接,最後在執行個體化的NormalMan()裡傳入Mike,最後列印出來NormalMan這個對象裡有name: "Mike"

如果用另外一個變量去接收b裡面singing的方法 ,再調用這個方法,這個時候就和運作一個普通函數一樣,這時再去列印this,this就為undefined

class Human{
	constructor(eyes=2,hands=2){
		this.eyes=eyes;
		this.hands=hands;
	}

	singing(){
		console.log('I can sing');
	}
}

let a = new Human(3,4);
console.log(a);

a.singing();

class NormalMan extends Human {
  	constructor(name='Flowke'){
  		super(1000,2000);
		this.feet=2;
        this.name=name;
	}

	singing(){
		console.log(this);
		/*console.log(`${this.name} can sing`);*/
	}
	run(){
		console.log('NormalMan can run');
	}
}

let b=new NormalMan('Mike');
console.log(b);
b.singing();
b.run();

let fnn=b.singing;
fnn();
           

那該怎麼去解決這個問題呢,如何讓這個this永遠指向new出來的這個執行個體?可以在constructor的構造函數裡寫上這句 this.singing=this.singing.bind(this);

class Human{
	constructor(eyes=2,hands=2){
		this.eyes=eyes;
		this.hands=hands;
	}

	singing(){
		console.log('I can sing');
	}
}

let a = new Human(3,4);
console.log(a);

a.singing();

class NormalMan extends Human {
  	constructor(name='Flowke'){
  		super(1000,2000);
		this.feet=2;
        this.name=name;
        this.singing=this.singing.bind(this);
	}

	singing(){
		/*console.log(this);*/
		console.log(`${this.name} can sing`);
	}
	run(){
		console.log('NormalMan can run');
	}
}

let b=new NormalMan('Mike');
console.log(b);
b.singing();
b.run();

let fnn=b.singing;
fnn();
           

this.singing=this.singing.bind(this);後面的this.singing就是指後面的singing()這個方法,後面綁定了this,那這個時候let fnn=b.singing,這裡的b.singing通路的就是this.singing,而這裡this.singing已經綁定了this的指向,這個時候去運作fnn,而這個this就是指構造的時候類的執行個體,這個時候運作fnn,就會發現列印出來的是mike也就是b這個執行個體化對象