ES6: Class基本语法

作者 Lei Zhang 日期 2019-03-21
ES6: Class基本语法

1. 理解

ES6引入Class的概念,以更接近传统语言的写法,作为对象的模板。

实际上,ES6的class可以看作是一个语法糖,因为它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。

ES5:

	function Point(x, y) {
this.x = x;
this.y = y;
}

Point.prototype.toString = function() {
reurn `(${this.x},${this.y})`;
}

var p = new Point(1, 2);

ES6:

class Point {
constructor(x, y){
this.x = x;
this.y = y;
}

toString() {
return `(${this.x},${this.y})`;
}
}

注意:定义类的方法时,不需要加function关键字,且两个方法间不需要逗号隔开

  • typeof Point;								//"function"
    Point === Point.prototype.constructor; //true

这证明类的数据类型本身就是函数,类本身就指向构造函数

  • 构造函数的prototype属性继续存在,且类定义的函数都定义于prototype上面

  • 类的新方法,可以直接添加在prototype上面

Object.assign(Point.prototype, {
func1(){},
func2(){}
});
  • 类中的所有方法都是不可枚举的(与ES5不同)

2. constructor方法

  • constructor方法默认返回实例对象(this),可以指定返回另一个对象

  • 类必须用new调用,否则会报错,而构造方法不会

3. 类的实例

  • 与ES5一样,实例的属性除非显示定义在其本身(即定义在this上),否则都是定义在原型上(即定义在class上)
class Point {

constructor(x, y) {
this.x = x;
this.y = y;
}

toString() {
return '(' + this.x + ', ' + this.y + ')';
}

}

var point = new Point(2, 3);

point.toString() // (2, 3)

point.hasOwnProperty('x') // true
point.hasOwnProperty('y') // true
point.hasOwnProperty('toString') // false
point.__proto__.hasOwnProperty('toString') // true
  • 同ES5,所有实例共享一个原型对象 p1.__proto__ === p2.__proto__ //true

生产中,可以通过Object.getPrototypeOf方法获取实例的原型,再为原型添加方法/属性(会应用于所有实例)

4. 注意点

  1. 类和模块内部,默认就是严格模式,不需要声明
  2. 不存在变量提升(hoist),类必须在声明之后才能调用(与继承有关)
  3. this的指向

类的方法内部如果含有this,它默认指向类的实例。但是,必须非常小心,一旦单独使用该方法,很可能报错

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

上面代码中,printName方法中的this,默认指向Logger类的实例。但是,如果将这个方法提取出来单独使用,this会指向该方法运行时所在的环境(由于 class 内部是严格模式,所以 this 实际指向的是undefined),从而导致找不到print方法而报错。

解决方法

  • class Logger {
      constructor() {
        this.printName = this.printName.bind(this);
      }
    
      // ...
    }
    <!--code6-->
  • 使用proxy //TODO

5. 静态方法

在方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用

class Foo {
static classMethod() {
return 'hello';
}
}

Foo.classMethod() // 'hello'

var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function

注意,如果静态方法包含this关键字,这个this指的是类,不是实例。

Todo…