class是es6引入的最重要特性之一。在没有class之前,我们只能通过原型链来模拟类。
基本用法
如果你用过java这样的纯面向对象语言,那么你会对class的语法非常熟悉。
class People { constructor(name) { //构造函数 this.name = name; } sayName() { console.log(this.name); } }
上面定义了一个People类,他有一个属性 name 和一个方法 sayName(),还有一个构造函数;
你可以这样使用这个类:
var p = new People("Tom"); p.sayName();
就像函数有函数声明和函数表达式两种定义方式,类也可以通过类表达式来定义:
let People = class { constructor(name) { //构造函数 this.name = name; } sayName() { console.log(this.name); } }
你可能以为类声明和类表达式的区别在于变量提升的不同。但是事实是无论是类声明还是类表达式的方式来定义,都不会有变量提升。所以下面的写法是错的:
var p = new People("Tom"); //错误,People 未定义 class People { //... };
类中的所有方法默认都是 strict mode
,所以不用再次声明了。
继承
通过关键字 extends
来继承一个类,并且,可以通过 super
关键字来引用父类。
class People { constructor(name) { //构造函数 this.name = name; } sayName() { console.log(this.name); } } class Student extends People { constructor(name, grade) { //构造函数 super(name); //调用父类构造函数 this.grade = grade; } sayGrade() { console.log(this.grade); } }
上面的例子中我们定义了一个 Student ,他是 People 的子类。
注意我们在 constructor 中是如何通过 super
调用父类的构造函数的。
getters & setters
现在我们可以通过 get
和 set
关键字来定义 getters 和 setters 了。
下面我们给 name
属性定义 getter 和 setter
class People { constructor(name) { //构造函数 this.name = name; } get name() { return this._name.toUpperCase(); } set name(name) { this._name = name; } sayName() { console.log(this.name); } } var p = new People("tom"); console.log(p.name); //TOM console.log(p._name); //tom p.sayName(); //TOM
仔细看上面的例子,搞清楚最后三行分别会输出什么,就明白getter 和 setter该怎么用了。
主要是要区分 this._name 和 this.name 的区别。因为我们定义了 name
的读写器,而没有定义 _name
的读写器,所以访问这两个属性的结果是不同的。
但是要注意一点,不要这样写:
set name(name) { this.name = name; }
因为给 this.name
赋值的时候会调用 set name
,这样会导致无限递归直到栈溢出。
静态方法
通过 static
关键字定义静态方法:
class People { constructor(name) { //构造函数 this.name = name; } sayName() { console.log(this.name); } static formatName(name) { return name[0].toUpperCase() + name.sustr(1).toLowerCase(); } } console.log(People.formatName("tom"));
静态方法一般用来提供一些工具方法。
私有属性
很不幸的时ES6并没有提供对私有属性的语法支持,但是我们可以通过闭包来实现私有属性。
var People = (function() { var p = new WeakMap(); class People { constructor(name) { //构造函数 var privateProperties = { name: name }; p.set(this, privateProperties); } sayName() { console.log(this.name); } get name() { return p.get(this).name; } } return People; })(); var p = new People("tom"); console.log(p.name); p.sayName(); var p2 = new People("bob"); console.log(p2.name); p2.sayName();