Appearance
ES6 Class
date: 2020-07-21 16:46:12 tags: [js]
ES5构造函数 和 class 对比
bash
# ES5构造函数
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function () {
return '(' + this.x + ', ' + this.y + ')';
};
# class
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
# 使用方式一致
var p = new Point(1, 2);class 中constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5 的构造函数Point,对应 ES6 的Point类的构造方法。
ES6 的类,完全可以看作构造函数的另一种写法。
构造函数的prototype属性,在 ES6 的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。
bash
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
# 等同于
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
};prototype对象的constructor属性,直接指向“类”的本身,这与 ES5 的行为是一致的。
javascript
Point.prototype.constructor === Point // true另外,类的内部所有定义的方法,都是不可枚举的(non-enumerable)。
javascript
class Point {
constructor(x, y) {
// ...
}
toString() {
// ...
}
}
Object.keys(Point.prototype)
// []
Object.getOwnPropertyNames(Point.prototype)
// ["constructor","toString"]constructor方法
constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
javascript
class Point {
}
// 等同于
class Point {
constructor() {}
}取值函数(getter)和存值函数(setter)
与 ES5 一样,在“类”的内部可以使用get和set关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为
javascript
class MyClass {
constructor() {
// ...
}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: '+value);
}
}
let inst = new MyClass();
inst.prop = 123;
// setter: 123
inst.prop
// 'getter'上面代码中,prop属性有对应的存值函数和取值函数,因此赋值和读取行为都被自定义了。
属性表达式
类的属性名,可以采用表达式。
javascript
let methodName = 'getArea';
class Square {
constructor(length) {
// ...
}
[methodName]() {
// ...
}
}
let square = new Square()
square.getAreaClass 表达式
javascript
const MyClass = class Me {
getClassName() {
return Me.name;
}
};上面代码使用表达式定义了一个类。需要注意的是,这个类的名字是Me,但是Me只在 Class 的内部可用,指代当前类。在 Class 外部,这个类只能用MyClass引用
javascript
let inst = new MyClass();
inst.getClassName() // Me
Me.name // ReferenceError: Me is not defined如果类的内部没用到的话,可以省略Me,也就是可以写成下面的形式。
javascript
const MyClass = class { /* ... */ };注意点
(1)严格模式
类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 实际上把整个语言升级到了严格模式。
(2)不存在提升
javascript
new Foo(); // ReferenceError
class Foo {}上面代码中,Foo类使用在前,定义在后,这样会报错,因为 ES6 不会把类的声明提升到代码头部。
(3)name 属性
由于本质上,ES6 的类只是 ES5 的构造函数的一层包装,所以函数的许多特性都被Class继承,包括name属性。
javascript
class Point {}
Point.name // "Point"(4)Generator 方法
如果某个方法之前加上星号(*),就表示该方法是一个 Generator 函数。
(5)this 的指向
类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错。
javascript
class Logger {
printName(name = 'there') {
this.print(`Hello ${name}`);
}
print(text) {
console.log(text);
}
}
const logger = new Logger();
const { printName } = logger;
printName(); // TypeError: Cannot read property 'print' of undefined