Skip to content

Class 是怎么实现的

🕒 Published at:

class 本质上来说,是 JS 类实现的一个语法糖,很多行为和 ES5 使用 function 关键字声明一个类是一致的。ES5 使用 function 关键字作为构造函数的时候,主要是利用 function 身上的 prototype 属性来实现继承的,而通过 class 关键字声明一个类也是通过 prototype 属性来实现继承的,使用 class 关键字声明一个类会让原型的写法更加清晰,更符合面向对象编程语言的风格。

一些相同的地方

  1. 都可以使用 extends 关键字实现继承,都可以继承静态方法

但也有一些不同的地方

使用 class 和 function 关键字声明类的不同

  1. class 声明的类必须使用 new,否则会报错。
  2. class 内部定义的原型方法是不可枚举的,而使用 function 关键字定义的原型方法是可枚举的。所谓可枚举就是可以通过 for...in 循环、Object.keys()等方法可以遍历出来。
  3. class 内部默认是严格模式
  4. class 不存在变量提升
  5. class中定义在prototype上的方法不能使用new来调用

将类转为普通构造函数的写法

js
class Example{
  constructor(name){
    this.name = name
  }
  func(){
    console.log(this.name)
  }
}

转为普通构造函数后

js
// 严格模式
'use strict'

function Example(name) {
  // 是否使用new关键字来调用
  if (!new.target) {
    throw new TypeError(
      `Class constructor Example cannot be invoked without 'new'`
    )
  }
  this.name = name
}

Object.defineProperty(Example.prototype, 'func', {
  value: function () {
    if (new.target) {
      throw new TypeError('Example.prototype.func is not a constructor')
    }
    console.log(this.name)
  },
  enumerable: false,
})

// 必须使用new关键字来调用
// Example()

// 不可遍历
// const e = new Example()
// for (const key in e) {
//   console.log(key)
// }

// Example.prototype上的方法不能使用new来调用
// new Example.prototype.func()