关于 ES5 中的对象与继承(ES5 中并没有类的概念,我们可以用构造函数来模拟类),我推荐大家看《JavaScript 高级程序设计》的第六章,讲的非常详细。我们现在来看一下 ES6 对类与继承做了哪些更新。
在 ES6 中新增了class
关键字,用于声明类。与构造函数类似,我们也建议类名的首字母大写。我们来看一个例子:
1 2 3 4 5 6 7 8 9 10 11
| class People { constructor(name, age) { this.name = name this.age = age } showName() { console.log(this.name) } } let p1 = new People('lily', 20) console.log(p1)
|
我们来看一下输出:
我们可以看出来,这和 ES5 中组合使用构造函数模式与原型模式得到的结果一致。所以我们也把 class 叫做“语法糖”,因为它可以让我们更快乐的写代码(因为写法更简单了嘿嘿)。我们在看一下 ES6 中如何实现继承,ES6 中出现了一个新的关键字extends
用于类的继承。
1 2 3 4 5 6 7 8 9 10 11 12
| class Coder extends People { constructor(name, age, skill) { super(name, age) this.skill = skill } showSkill(){ console.log(this.skill) } }
let c1 = new Coder('ming', 25, 'code') console.log(c1)
|
我们在看一下输出结果:
在 ES6 中,我们还可以使用设置方法的形式设置属性,具体看下例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class People { constructor(name, age) { this.name = name this.age = age } get sex() { return 'female' } showName() { console.log(this.name) } } let p1 = new People('lily', 20) console.log(p1.sex)
|
我们通过get
关键字设置了一个属性 sex,并且通过 p1.sex 读取了 sex 属性。但是 get 关键字总能够让 sex 属性被读,并不能让 sex 属性被写。想让 sex 属性被写我们还需要set
。但是我们要注意不能这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class People { constructor(name, age) { this.name = name this.age = age } get sex() { return 'female' } set sex(val) { this.sex = val } } let p1 = new People('lily', 20) p1.sex = 'male'
|
以上代码会提示“Maximum call stack size exceeded”,原因是陷入了死循环。因为执行 p1.sex = ‘male’ 时,会调用 set sex(){} 方法。set sex(){} 方法内部设置 this.sex = val 时,也会调用 set sex(){} 方法, set sex(){} 方法内部执行 this.sex = val 时又调用了 set sex(){} 方法。因此这是一个死循环,我们应该这样写:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class People { constructor(name, age) { this.name = name this.age = age this._sex = 'female' } get sex() { return this._sex } set sex(val) { this._sex = val } }
let p1 = new People('lily', 20) console.log(p1.sex) p1.sex = 'male' console.log(p1.sex)
|
当我们需要对值进行一些业务逻辑处理再进行读和写时,就应该使用这种方法。通过这种方式设置的属性也可以被子类继承。
我们再看一下如何在 ES6 中定义静态属性和方法。ES6 中使用static
关键字定义静态方法:
1 2 3 4 5 6 7 8 9 10 11
| class People { constructor(name, age) { this.name = name this.age = age } static getCount() { return 5 } }
console.log(People.getCount())
|
ES6 的 class 内部目前并不能定义静态属性,我们可使用 ES5 中定义静态属性的方法。
1 2 3 4 5 6 7 8
| class People { constructor(name, age) { this.name = name this.age = age } } People.count = 1 console.log(People.count)
|
再次强调:class 只是“语法糖”,使用 class 定义出的类,底层还是和 ES5 中组合使用构造函数和原型方式定义出的“类”一样。我们可以使用 type of 方式检测上面示例中的 People,结果是 function。
下面的例子使用 babel 将 ES6 转化成 ES5,让大家更好的理解一下: