天天看点

自我学习之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这个实例化对象