传统 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 // true
typeof 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 // undefined
p.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 // undefined
Boy.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 关键字。
评论