传统 JavaScript 没有类的概念,只有对象。为了让 JavaScript 更像一门面向对象的语言,ES6 引入了 Class(类)的概念,通过 class 关键字定义类。
先看个使用 es5 构造函数创建实例以及 class 创建实例的对比:
// es5构造函数function Person(name,age){ // 实例属性 this.name = name this.age = age}// 原型属性Person.prototype.tag = 'man'// 原型方法Person.prototype.say = function(){ console.log(this.name+'在说话')}
var p = new Person('张三',18)p.say() // 张三在说话
// ES6 class写法class Person1{ // 构造函数 constructor(name,age){ // 实例属性 this.name = name this.age = age } // 原型属性 tag = 'man' // 原型方法 say(){ console.log(this.name+'在说话') }}var p1 = new Person1('李四',18)p1.say() // 李四在说话
p1.say === Person1.prototype.say // truetypeof Person1 // 'function'
复制代码
从例子中,可以看出 class 本质还是函数,p1 实例的 say 属性与 Person1 类原型中的 say 属性是相等的。
实际上 class 的属性和函数也都是定义在 prototype 属性中,只是 ES6 将 prototype 属性相关操作封装在 class 中,省去了我们之间操作 prototype 属性。
静态属性和方法
静态属性和方法使用 static 关键字修饰,只能通过类本身使用,不能被实例访问。
class Person{ static name = 'class' static getName(){ console.log('static getName') }}// 通过类本身可以访问到Person.name // 'class'Person.getName // 'static getName'
// 通过实例访问不到let p = new Person()p.name // undefinedp.getName() // undefined
复制代码
这个例子我们没有声明构造函数,为啥没报错呢?因为没声明时,会自动隐式添加一个空的构造函数。
继承
ES6 可以通过 extends 关键字实现类的继承。
// 父类class Person{ constructor(name,age){ this.name = name this.age = age } static tag = 'person' getName(){ return this.name }}
// 子类class Boy extends Person{ constructor(name,age,sex){ // 执行父类构造函数 super(name,age) this.sex = sex } getSex(){ return this.sex }}
var b = new Boy('张三',18,'男')b.getName() // '张三'b.getSex() // '男'b.tag // undefinedBoy.tag // 'person'
复制代码
父类的静态函数无法被实例继承,但可以被子类继承,子类可以通过自身去访问,而不是通过子类实例。
注意点:
class 只能与 new 关键字配置使用
class Person(){}new Person() // 正确Person() // 报错:类构造器无法执行
复制代码
class 定义类不存在变量提升
var p = new Person() // 报错:Person没有定义class Person(){}
复制代码
类中声明函数,不需要加 function 关键字
class Person(){ say function(){ // 语法错误:UnExpected token function }}
复制代码
this 指向问题
class Person(){ constructor(name){ this.name = name } getName(){ return this.name }}
const {getName} = new Person('张三')getName() // 报错:Cannot read property 'name' of undefined
复制代码
getName()函数是在全局环境中执行,this 指向的是全局环境。但 ES6 的 class 关键字中使用了严格模式,而严格模式下 this 不能指向全局环境,而是指向 undefined,所以通过 undefined 应用 name 就报错。
解决办法:在构造函数中重新绑定 this
class Person{ constructor(name){ this.name = name // 重新绑定getName函数中的this指向实例 this.getName = this.getName.bind(this) } getName(){ return this.name }}const {getName} = new Person('张三')getName() // 张三
复制代码
自此我们学习了 ES6 的 class 关键字。
评论