Class
ES6中的Class与继承
Class的特点
- ES6的
class可以看作是一种语法糖,它实质上还是基于原型的面向对象编程的一种封装。
- 方法与方法之间不需要逗号分隔,定义方法的时候前面不需要加上
function关键字。
- 类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
- 类必须使用
new调用,否则会报错。
- 类的属性和方法,除非显式定义在其本身(即定义在
this对象上),否则都是定义在原型上(即定义在class上)。
- 类的所有实例共享一个原型对象。
- 在“类”的内部可以使用
get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。
- 类的属性名可以采用表达式的形式定义,也可以使用表达式作为类的名称。
继承
- 使用
extends关键字实现继承,子类可以继承父类的属性和方法。
- 子类必须在
constructor()方法中调用super(),否则会报错。super()用于调用父类的构造函数,确保子类实例继承父类的属性和方法。
- 在子类的构造函数中使用
super()之后,才能使用this关键字。
- 父类的静态方法可以被子类继承。
- 子类的静态方法中使用
super调用父类的静态方法时,方法内部的this指向当前子类,而不是子类的实例。
- 子类继承父类后,如果子类没有定义
constructor()方法,将默认添加一个空的constructor()方法。
- ES6的继承是通过软拷贝实现的,父类的属性和方法被复制到子类上。修改子类的属性或方法不会影响到父类。
使用super关键字
super作为函数使用时,代表父类的构造函数。子类的构造函数中必须执行一次super()。
super作为对象使用时,在普通方法中指向父类的原型对象,在静态方法中指向父类本身。
- 使用
super调用父类的方法时,方法内部的this指向当前的子类实例。
- 为了避免
this指向错误,使用super的时候必须显式指定是作为函数、还是作为对象使用,否则会报错。
new.target属性
new.target是一个内置的元属性,用于确定构造函数是怎么调用的。
- 当构造函数使用
new命令调用或Reflect.construct()调用时,new.target会返回被调用的构造函数。
- 子类继承父类时,
new.target会返回子类。
类的注意点
- 类和模块的内部,默认就是严格模式,所以不需要使用
use strict指定运行模式。
- 类不存在变量提升,子类必须保证在父类之后定义。
- 类的
name属性总是返回紧跟在class关键字后面的类名。
- 类的内部调用
new.target,返回当前类。
- 子类继承父类时,
new.target会返回子类。
私有属性和私有方法
- ES2022正式为
class添加了私有属性和私有方法,私有属性的属性名必须包括#,如果不带#,会被当作另一个属性。
- 私有属性和私有方法可以设置
get和set方法。
- 私有属性不限于从
this引用,只要是在类的内部,实例也可以引用私有属性。
- 静态方法和私有方法的区别是,静态方法作为类的属性,不会被实例继承,而私有方法是定义给当前类内部使用,其子类不可以调用。
in运算符
in运算符可以用来判断私有属性是否存在,返回一个布尔值。
in运算符对于Object.create()、Object.setPrototypeOf形成的继承,是无效的,因为这种继承不会传递私有属性。
静态块
- 类的内部有一个
static代码块,它的好处是将静态属性的初始化逻辑写入类的内部,而且只运行一次。
- 每个类允许有多个静态块,每个静态块中只能访问之前声明的静态属性。静态块的内部不能有
return语句。
- 静态块内部可以使用类名或
this,指代当前类。