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); //1console.log(p._name); //2p.sayName(); //3
仔细看上面的例子,搞清楚最后三行分别会输出什么,就明白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并没有提供对私有属性的语法支持,但是我们可以通过闭包来实现私有属性。
关于 WeakMap,会在下一篇博客仔细讲解。 为什么要用WeakMap呢?因为WeakMap 用object作为key,并且是一个弱引用,也就是说,WeakMap对这个对象的引用并不会导致GA无法回收这个对象(GA计算对象引用数量的时候并不会计算弱引用)。
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();