x-note
Search…
ECMAScript 6 class
ES6 正式引入了 Class 的概念,可以通过class关键字去声明一个类。在此之前,class一直作为 JavaScript 的保留字,如果想要在 JavaScript 生成实例对象,只能通过构造函数的方式。
1
function Point(x, y) {
2
this.x = x;
3
this.y = y;
4
}
5
Point.prototype.toString = function () {
6
return `[${this.x}, ${this.y}]`;
7
}
8
let p = new Point(1, 2);
9
p.toString(); // [1, 2]
10
11
// 新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法
12
class PointB {
13
constructor(x, y) {
14
this.x = x;
15
this.y = y;
16
}
17
toString() {
18
return `[${this.x}, ${this.y}]`
19
}
20
}
21
let p2 = new PointB(1, 2);
22
p.toString(); // [1, 2]
Copied!
ES6 的类,可以看作是构造函数的语法糖
1
class A {}
2
typeof A; // "function"
3
A === A.prototype.constructor; // true
Copied!

声明 class

一般声明
1
class A {}
Copied!
class 表达式
1
const A = class {}
Copied!
声明继承关系(不支持多继承)
1
class A {}
2
class B extends A {}
Copied!

调用 class

类必须使用new操作符调用,如果不使用new操作符调用,则会抛出一个TypeError
1
class A {}
2
A(); // Uncaught TypeError: Class constructor A cannot be invoked without 'new'
Copied!
不传递参数时可以省略括号
1
class A {}
2
let a = new A;
Copied!

class 的方法

class的普通方法
1
class A {
2
method() {}
3
}
Copied!
class的静态方法
1
class A {
2
static staticMethod() {
3
return 1;
4
}
5
}
6
A.staticMethod(); // 1
Copied!
class的私有方法
1
// 私有变量和方法仍在提案中,可以利用 Symbol 实现私有方法
2
const bar = Symbol('bar');
3
const snaf = Symbol('snaf');
4
5
export default class myClass{
6
7
// 公有方法
8
foo(baz) {
9
this[bar](baz);
10
}
11
12
// 私有方法
13
[bar](baz) {
14
return this[snaf] = baz;
15
}
16
17
// ...
18
};
19
20
// 提案中的私有方法声明方式
21
class A {
22
#method() {}
23
}
Copied!
class内的gettersetter
1
class A {
2
constructor(val) {
3
this._val = val || null;
4
}
5
get value() {
6
return this._val;
7
}
8
set value(val) {
9
if (this._val !== val) {
10
this._val = val;
11
console.log('value changed');
12
}
13
}
14
}
15
let a = new A;
16
a.value; // null
17
a.value = 1; // value changed
18
a.value = 1;
Copied!
class内的Generator方法
1
class A {
2
constructor(...args) {
3
this.args = args;
4
}
5
* [Symbol.iterator]() {
6
for (let arg of this.args) {
7
yield arg;
8
}
9
}
10
}
11
12
for (let x of new A('hello', 'world')) {
13
console.log(x);
14
}
15
// hello
16
// world
Copied!
类的内部定义的所有方法都是不可枚举的
1
class A {
2
method1() {}
3
method2() {}
4
}
5
let a = new A;
6
Object.keys(Reflect.getPrototypeOf(a)); // []
7
8
function B () {}
9
B.prototype.method1 = function () {}
10
B.prototype.method2 = function () {}
11
let b = new B;
12
Object.keys(Reflect.getPrototypeOf(b)); // ["method1", "method2"]
Copied!
class的方法内的this并不会与实例绑定
1
class A {
2
method1() {
3
this.method2();
4
}
5
method2() {
6
console.log('method2 of class "A"');
7
}
8
}
9
a = new A;
10
const { method1 } = a;
11
method1(); // TypeError: Cannot read property 'method2' of undefined
Copied!

class 的静态属性、实例属性和私有属性

ES6 中 class 不能在class 内部直接定义静态属性、实例属性和私有属性。ES7 开始允许在 class 内部直接声明静态属性、实例属性实。class 的私有属性,仍处于提案中。
1
class A {
2
consturctor() {
3
this.x = 1; // 只能在构造函数内声明实例属性
4
}
5
}
6
A.staticProp = 1; // 声明 A 的静态属性
7
8
// ES7 支持的新语法
9
class B {
10
static staticProp = 1;
11
x = 1;
12
}
Copied!
私有属性仍在提案中
1
// 通过 Symbol 实现私有属性
2
const pVal = Symbol('privateVal');
3
4
class A {
5
constructor(x) {
6
this[pVal] = undefined;
7
}
8
get value() {
9
return this[pVal];
10
}
11
set value(val) {
12
this[pVal] = val;
13
}
14
}
15
16
// 提案中的私有属性声明
17
class A {
18
#x;
19
constructor(x = 0) {
20
#x = +x; // 写成 this.#x 亦可
21
}
22
get x() { return #x }
23
set x(value) { #x = +value }
24
}
Copied!

变量提升

class不存在变量提升
1
a = new A; // ReferenceError: A is not defined
2
class A {}
Copied!

严格模式

类的内部默认采用严格模式
1
class A {
2
method1() {
3
function fn () {
4
console.log(this);
5
}
6
fn();
7
}
8
}
9
a.method1(); // undefined
Copied!