学习ES6中的类

JS 在 ES5 及更早版本都不存在类。与类最接近的是:创建一个构造器,然后将方法指派到该构造器的原型上。这种方法通常被称为创建一个自定义类型。在 ES6 中最终引入了类。

类的声明

下面是一个基本的类声明:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Person {
// 等价于 Person 构造器
constructor(name) {
this.name = name;
}
// 等价于 Person.prototype.getName
getName() {
console.log(this.name);
}
}
let max = new Person('Max');
max.getName(); // 'Max'

类与自定义类型的区别

  1. 类声明不会被提升,这与函数定义不同。类声明的行为与 let 相似,因此在程序的执行到达声明处之前,类会存在于暂时性死区内。
  2. 类声明中的所有代码会自动运行在严格模式下,并且也无法退出严格模式。
  3. 类的所有方法都是不可枚举的,这是对于自定义类型的显著变化,后者必须用 Object.defineProperty() 才能将方法改变为不可枚举。
  4. 类的所有方法内部都没有 [[Construct]] ,因此使用 new 来调用它们会抛出错误。
  5. 调用类构造器时不使用 new ,会抛出错误。
  6. 试图在类的方法内部重写类名,会抛出错误。

类表达式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 匿名类表达式
let Person = class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
// 具名类表达式
let Person = class PersonClass {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}

具名类表达式的标识符(如上面代码中的 PersonClass),只在类内部存在,因此只能用在类方法的内部。在类的外部,是不存在与标识符的绑定(typeof PersonClass === 'undefined')。

类表达式一个有趣用途是立即调用类构造器,以创建单例。为此你必须使用 new 来配合类表达式,并在表达式后面添加括号。如:

1
2
3
4
5
6
7
8
9
10
11
12
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('Max');
person.sayName(); // 'Max'

访问器属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Person {
constructor(name) {
this.name = name;
}
get name() {
return this.name;
}
set name(value) {
this.name = value;
}
}

生成器方法

只要在方法名称前附加一个星号(*),就可以定义一个生成器。

1
2
3
4
5
6
7
8
class MyClass {
*createInterator() {
yield 1;
yield 2;
yield 3;
}
}