es6学习笔记-class之继承

上一篇学习了class的概念,在es5时,对象的继承有好几种,原型链继承,借用构造函数继承,组合继承,原型式继承,寄生式继承以及寄生组合式继承,都是按照函数的形式去集成的,现在class也有它的继承方式,简化了操作。

extends

关键字extends,直接通过这一个关键字就可以实现继承。

class Person{} class Child extends Person{}

上面代码定义了一个Child类,该类通过extends关键字,继承了Person类的所有属性和方法,所以Child就直接复制了一份Person类。简单的开场方式,是不是比es5的继承方式简单多了,哈。。

super关键字

在子类中调用super(),说明是表示父类的构造函数,用来新建父类的this对象。

class Person { constructor(name, age) { this.name = name; this.age = age; } say(name) { console.log(`${name} is saying`) } } class Child extends Person { constructor(name, age, color) { super(name, age); this.color = color } jump(name) { console.log(`${this.name} is jumping`) } } var peter = new Child('peter',18,'red'); console.log(peter); // Child {name: "peter", age: 18, color: "red"} peter.jump() // peter is jumping

子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

class Person{} class Child extends Person{ constructor(){} } var peter = new Child() // Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor

上面代码中,Child继承了父类Person,但是它的构造函数没有调用super方法,导致新建实例时报错。所以说super()是在继承中重要的一环。
另外,如果子类中没有显示constructor,即使不加super,也不会报错,因为class中会默认有constructor,同样的道理,也会有super()

class Child extends Child {} // 等同于 class Child extends Child { constructor(...args) { super(...args); } } ps: ES5的继承和ES6的继承的区别: ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。 ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。

另一个需要注意的地方是,在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。这是因为子类实例的构建,基于父类实例,只有super方法才能调用父类实例。

class Perosn { constructor(name, age) { this.name = name; this.age = age; } } class Child extends Person { constructor(name, age, color) { this.color = color; // ReferenceError:Person is not defined super(name, age); this.color = color; // 正确 } }

super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

第一种情况,super作为函数调用时,代表父类的构造函数,类似于super()。

ES6 要求,子类的构造函数必须执行一次super函数。

class A { constructor() { console.log(new.target.name); } } class B extends A { constructor() { super(); } } new A() // A new B() // B super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B,因此super()在这里相当于A.prototype.constructor.call(this)。继承了A的this为B所用。
上面代码中,new.target指向当前正在执行的函数。可以看到,在super()执行时,它指向的是子类B的构造函数,而不是父类A的构造函数。也就是说,super()内部的this指向的是B。因此super()在这里相当于A.prototype.constructor.call(this)。

super()只能用在子类的构造函数constructor之中,用在其他地方就会报错。

class Person {} class Child extends Person { jump() { super(); // error } }

上面的例子,在Child子类中的constructor之外的方法中用了super(),会报错,因为super函数只能用在构造函数constructor中。

第二种情况,super作为对象时,

在普通方法中,指向父类的原型对象

class Person { constructor(name,age) { this.name = name; this.age = age; } say(){ console.log(this.age) } p(){ return 2 } } class Child extends Person { constructor(name,age, color) { super(name,age); //该super代表的是用函数的形式 this.age = 25; this.color = color; console.log(super)//使用super的时候,必须显式指定是作为函数、还是作为对象使用,否则会报错。如果只写super,没法判断是对象还是方法 console.log(super.p()); } say1(){ super.say() } } var peter = new Child('peter',18,'red') peter.p() // 2 peter.say1() // 25

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpjzfp.html