javascript基础系列之ES6中的类/super

227 阅读3分钟

ES6类有很多新特性

1. 类的声明不具有变量提升效果,在执行之前一直会在临时死区

2. 类声明内的所有代码会自动在严格模式下运行,且无法强行让代码脱离严格模式

3. 在自定义类型的时候,Object.defineProperty()方法手工指定某个方法不可枚举;而在类中,所有方法都是不可枚举

4. 每个类都有名为[[Constructor]]的内部方法,通过关键字new调用不含[[Constructor]]的方法会导致程序抛出错误


5. 在使用除关键字new之外的其他方式调用构造函数会导致程序抛出错误6. 在类中修改类名会抛出错误7. 表达式形式

8. 类作为一等公民,可以作为参数传入9. 支持在内部直接定义访问器属性


10. 可计算成员名称:


11. 生成器方法


12. 静态成员,基类静态方法在派生类中可以使用13. 类方法的遮蔽


14.  Super的使用:

在对象中的super行为

在ES6中新增了对象方法的简写语法:以下写法唯一的区别就在于增强写法可以使用super关键字。


简化原型访问的Super引用:重写对象实例的方法,有需要调用与它同名的原型方法,在ES5中如下


ES6中使用super即可


另外在es6中不使用增强写法也不可以使用super关键字


原因:使用增强写法的时候会给getGreeting增加一个[[HomeObject]]属性来确定后续的运行过程,依靠它来找到原型,因此super.getGreeting()才与person.getGreeting.call(this)等价。


super关键字在多重继承的时候非常有用,因为super的引用不是动态变化的,它总是指向正确的对象。

下方代码栈溢出的原因是因为,relative的原型对象是friend,relative.getGreeting()会调用friend.getGreeting()。但是此时的this的指向relative的,因此friend的getGreeting方法中使用Object.getPrototypeOf(this).getGreeting.call(this)会一直调用friend自身的getGreeting方法。


那么如果去掉.call(this)呢?

这是由于第一次:this为relative,relative.getGreeting()是调用了friend.getGreeting()方法

第二次:this为friend,friend.getGreeting()得以调用person.getGreeting()


使用super以后:得到想要的结果


在类中的super行为

1) 只可以在派生类的构造函数中运行super,如果在非派生类(不是在extends声明的类)或函数中使用会抛出错误

2) 狗仔函数中访问this之前一定要先调用super(),它负责初始化this(super()调用会生成一个空对象,作为context来调用父类的constructor,返回this对象,作为子类constructor的context继续调用构造函数。)

3)如果不想调用super(),那么就让类的构造函数返回一个对象

4)静态成员调用


5)继承


15. 派生自表达式的类:只要表达式可以被解析为一个函数并且具有[[Constructor]]属性和原型,就被extends派生


16. 内建对象的继承:实用之处是原本返回内建对象实例自身的方法会返回派生类的实例

es5的类:this的值先由派生类创造,再由基类的其他属性来修饰。




下方中虽然myArray继承了Array的length属性,但是没有继承数组数目更改时length变化的行为。

即length发生变化的时候并没有调用Aarray.apply(this,arguments)导致myArray创建的数组实例的length属性没有更新。



es6的类:ES6的继承则是先由基类创建this的值,然后由派生类的构造函数来修饰。



使用es6继承MyArray因此可以完全继承Array的行为


17. Symbol.species属性:用于定义返回函数的静态访问器属性(不懂,。。先略过)18. new.Target:构造函数中使用,模仿抽象类

总结:用es5的代码模仿es6的类