写点什么

重学 JS | Class

用户头像
梁龙先森
关注
发布于: 2021 年 01 月 15 日
重学JS | Class

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

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


注意点:

  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 关键字。

发布于: 2021 年 01 月 15 日阅读数: 23
用户头像

梁龙先森

关注

脚踏V8引擎的无情写作机器 2018.03.17 加入

还未添加个人简介

评论

发布
暂无评论
重学JS | Class