天天看点

ES6中class的constructor以及super使用介绍ES6中class详解,class的constructor以及super使用

ES6中class详解,class的constructor以及super使用

下面开始正文的介绍:

1.定义

Constructor是一种用来 创建和初始化class类创建的对象 的特殊方法,一般写在class类的方法里面,使类创建出来的新对象可以继承到class类上面绑定的方法以及属性, es6类中的constructor构造方法对应的是es5中的构造函数。

  • 注意:【在一个class类中只能有一个constructor的方法名,多余一个就会报错】

例如:

class Person {
	constructor () {
		this.name = ‘Lily’
	}
	showName () {
		console.log('Liming')
	}
}

var aa = new Person();

aa.showName(); //'Liming'
console.log(aa.name); //‘Lily’
           
  • 注意:若没有显式的指定constructor函数,则会添加一个默认的空的constructor这个方法
  • 注意: 在constructor中的this指的是实例对象

2.es6中的class

class属于es6中的一种语法糖,使用的 例子:

//es5写法
function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);

//es6写法
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
	toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}
           

在es6中定义类的方法不需要加function这个关键字

//这两者是等价的
Point === Point.prototype.constructor //true
           
  • 注意:class类本身就是函数,并且自身就指向它的构造函数,类上所有的方法实际上都是定义在类的prototype属性上,当然也包括constructor()方法。所以当向类上添加方法时,要添加在类的prototype属性上,可以使用Object.assign()方法同时添加多个。

举个?:

class Point {
  constructor(){
    // ...
  }
}

Object.assign(Point.prototype, {
  toString(){},
  toValue(){}
});
           
  • 注意:在类中定义的方法,如果前面加上static关键字,则表明这个方法不会被实例化出来的新对象所继承,实例化的对象是无法调用到的,而是要通过类本身来调用,这样的方法称之为 静态方法。
  • 此时,若静态方法中含有this,指向的并不是实例化的新对象了,而是指向类本身。
-可以使用extends来继承父类上面的方法,并且父类上面的静态方法也可以继承到,例子如下:
//子类继承父类的写法
class Bar {
	static sayAge () {
		console.log('19')
	}
}

class Foo extends Bar {
}
Foo.sayAge() //'19'
           

3.constructor的详解

constructor默认会返回this这个实例对象,也可以指定返回另一个对象,constructor会在类实例化一个新对象时,自动调用这个方法

4.super关键字

对象函数中的this指向的是当前的函数所在的对象,而super指向的是当前函数所在对象的原型,比this更深了一个层次。在子类的构造函数中调用super(),相当于调用父类的constructor。可以举个?:

const proto = {
  foo: 'hello'
};

const obj = {
  foo: 'world',
  find() {
    return super.foo;
  }
};

Object.setPrototypeOf(obj, proto);//使用setPrototypeOf给obj设置原型对象为proto
obj.find() // "hello"
           
注意:super用来表示原型对象时,只能用在对象的方法中,用在其他地方都会报错。super的常用场景,比如当子类重写了父类的某个同名方法或者属性后,如果这时还想在子类中调用这个父类的这个同名方法或属性,就可以直接使用super关键字指向父类,调用这个父类原有的方法或者属性

js引擎只在对象的方法中识别super,对于原型对象上的realName属性,super.realName === object.getPrototypeOf(this).realName

关于super中的this指向
注意:当使用super指向原型对象中的一个方法时,方法中的this不指向原型对象,而是指向当前所存在的子类对象。
父子类关系时,子类中的this问题
  • 当子类在extends继承父类时,若想在子类中使用constructor构造函数,则必须先在子类的constructor中调用super(),(若父类的constructor函数有参数传入,那么这个时候需要在super中传入参数,即super(参数)),这一步相当于先调用父类的constructor函数,无论父类中有没有写constructor函数,都要调用super()。(因为前面讲过父类会隐式的创建一个空的constructor函数)

注意:子类在继承父类时,子类中是找不到this的,没有自己的this对象,只能使用super继承父类中的this对象,然后在加工。

即在ES6的继承,需要先创建父类的this,子类调用super继承父类的this对象,然后再用子类的构造函数对this进行加工。

这里另外说一下与es5继承方式的区别:

es5的继承,实质是先创造子类的实例对象 this ,然后再将父类的方法添加到 this 上面( Parent.apply(this) )

举例如下

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


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

应该修改为:

class Demo2 extends Demo{
	constructor(x,y){
		super(x,y);
		console.log(super.x); //undefined
		console.log(this.x); //这时候this是可以找到的,可以new一个实例对象,给x,y赋值试一下
	}
}
           

继续阅读