class
前面复习过了 Es5 的对象创建与继承,
接下来总结 Es6 的继承。
简述
ES6 的 class 只是一个语法糖,让原型对象的写法更清晰,更像面对对象编程的语法。
还是用以前的例子展示基础用法:
1 | class Animal { |
上面的测试可以表明:没毛病,和组合式继承的效果一毛一样
为原型添加方法
1 | class Animal { |
可以看到一种方法是从构造函数找到prototype
再使用Object.assign
完成方法的添加,这种写法比对象字面量的写法好处在于原型的constructor
没有被重写。因为原型已经被浅克隆。
第二种方法是使用Object.getPrototypeOf(obj)
找到原型。__proto__
也可以找到,但这个是不被推荐的。
ps:后来试了一下用对象对字面量的写法好像不管用:
1 | class Animal { |
立即执行的类
1 | let dog = new (class Animal { |
私有属性
利用 Symbol 值的唯一性,将私有方法的名字命名为一个 Symbol 值。
1 | const home = Symbol("home"); |
显然,其它模块拿不到 dog[home]方法,因为是 Symbol 值。因此达到私有属性和私有方法的效果。
Class 的取值函数(getter)和存值函数(setter)
和普通对象一样,class 的内部可以使用 get 和 set 关键字,对属性设置存值函数和取值函数拦截属性的存取行为。
1 | class Animal { |
还有一种写法是
1 | Object.defineProperty(Animal.prototype, "color", { |
静态方法
所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上 static 关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
1 | class Animal { |
从例子中可以看出来
- class 的静态方法可以被子 class 继承
- 实例不能调用静态方法
- 静态方法可以和非静态方法重名
new.target 属性
new.target 一般用在构造函数之中,返回 new 命令作用于的那个构造函数。如果构造函数不是通过 new 命令调用的,new.target 会返回 undefined,因此这个属性可以用来确定构造函数是怎么调用的。
class 继承
简述
class 通过 extends 关键字实现继承。
1 | class Animal { |
ES5 的继承,实质是先创造子类的 this 然后将父类的方法添加到 this 上面(Animal.apply(this))可以看上篇的借用构造函数。
ES6 的继承,实质是先将父类的实例对象的属性和方法添加到 this 上面(所以必须先调用 super 方法),然后再用子类的构造函数修改 this
super 关键字
super 可以当函数,也可以当作对象使用。使用方法不同。
当作函数使用时相当于父类的构造函数,就是上面例子中的应用。
第二种情况是 super 作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
在子类普通方法通过 super 调用父类方法时,方法内部的 this 指向当前子类实例;在子类的静态方法中通过 super 调用父类的方法时,方法内部的 this 指向当前的子类。