重学JS | class

这是我参与更文挑战的第12天,活动详情查看:更文挑战

[重学JavaScript系列文章连载中…]

传统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' 
复制代码

父类的静态函数无法被实例继承,但可以被子类继承,子类可以通过自身去访问,而不是通过子类实例。

注意点:

  1. class只能与new关键字配置使用
class Person(){}
new Person()  // 正确
Person() // 报错:类构造器无法执行
复制代码
  1. class定义类不存在变量提升
var p = new Person()  // 报错:Person没有定义
class Person(){}
复制代码
  1. 类中声明函数,不需要加function关键字
class Person(){
	say function(){ // 语法错误:UnExpected token function
  }
}
复制代码
  1. 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关键字。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享