JavaScript 系列之类(一)

682 阅读2分钟

这是我参与8月更文挑战的第16天,活动详情查看:8月更文挑战

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

一、ES6 中的类与 ES5 中的类

1.1 constructor

ES6 中:

class Person {
  constructor(name) {
    this.name = name;
  }

  sayHello() {
    return 'hello, I am ' + this.name;
  }
}

var kevin = new Person('Kevin');
kevin.sayHello(); // hello, I am Kevin

ES5 中:

function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function () {
  return 'hello, I am ' + this.name;
};

var kevin = new Person('Kevin');
kevin.sayHello(); // hello, I am Kevin

我们可以看到 ES5 的构造函数 Person,对应 ES6 的 Person 类的 constructor 方法。

注意:ES6 类的内部所有定义的方法,都是不可枚举的(non-enumerable)

在 ES6 中:

Object.keys(Person.prototype); // []
Object.getOwnPropertyNames(Person.prototype); // ["constructor", "sayHello"]

在 ES5 中:

Object.keys(Person.prototype); // ['sayHello']
Object.getOwnPropertyNames(Person.prototype); // ["constructor", "sayHello"]

1.2 实例属性

在 ES6 中,以前我们定义实例属性,只能写在类的 constructor 方法里面。比如:

class Person {
  constructor() {
    this.state = {
      count: 0
    };
  }
}

然而现在有一个提案,对实例属性和静态属性都规定了新的写法,而且 Babel 已经支持。现在我们可以写成:

class Person {
  state = {
    count: 0
  };
}

在 ES5 中:

function Person() {
  this.state = {
    count: 0
  };
}

1.3 静态方法

所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上 static 关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为静态方法

在 ES6 中:

class Person {
  static sayHello() {
    return 'hello';
  }
}

Person.sayHello() // 'hello'

var kevin = new Person();
kevin.sayHello(); // TypeError: kevin.sayHello is not a function

在 ES5 中:

function Person() {}

Person.sayHello = function() {
  return 'hello';
};

Person.sayHello(); // 'hello'

var kevin = new Person();
kevin.sayHello(); // TypeError: kevin.sayHello is not a function

1.4 静态属性

静态属性指的是 Class 本身的属性,即 Class.propName,而不是定义在实例对象(this)上的属性。

在 ES6 中,以前我们添加静态属性只可以这样:

class Person {}

Person.name = 'kevin';

因为上面提到的提案,现在可以写成:

class Person {
  static name = 'kevin';
}

在 ES5 中:

function Person() {};

Person.name = 'kevin';

1.5 new

注意:类必须使用 new 调用,否则会报错。普通构造函数不用 new 也可以执行。

class Person {}

Person(); // TypeError: Class constructor Foo cannot be invoked without 'new'

1.6 getter 和 setter

在 ES6 中与 ES5 一样,在类的内部可以使用 get 和 set 关键字,对某个属性设置存值函数和取值函数,拦截该属性的存取行为。

class Person {
  get name() {
    return 'kevin';
  }
  set name(newName) {
    console.log('new name 为:' + newName)
  }
}

let person = new Person();

person.name = 'daisy';
// new name 为:daisy

console.log(person.name);
// kevin

在 ES5 中:

function Person(name) {}

Person.prototype = {
  get name() {
    return 'kevin';
  },
  set name(newName) {
    console.log('new name 为:' + newName)
  }
}

let person = new Person();

person.name = 'daisy';
// new name 为:daisy

console.log(person.name);
// kevin