class 转换为 function 要注意什么地方?

2023/9/6

ES6之前,js的类都是由函数来实现的,那如果我想把 class 转为 function, 需要注意什么呢?

# 开始转换

语法糖,本质上还是个构造函数,我们先实现一个基本的function版本

类👇

class Example {
  construcor(name) {
    this.name = name;
  }

  getName() {
    console.log(this.name);
  }
}

函数👇

function Example(name) {
  this.name = name;
}

Example.prototype.getName = function () {
  console.log(this.name);
};

# 注意的点

类是严格模式的,所以要在构造函数上面加上"use strict";

"use strict"
function Example(name) {
  this.name = name;
}
/*
	...
*/

类只能通过new 来调用,不能直接来调用,所以我们是不能直接执行 Example()的,执行会报错

怎么来实现呢? —— 通过验证 this 的指向,通过new 调用的 this 是类的实例,而直接调用的 this 则是 window

("use strict");
function Example(name) {
  if (!(this instanceof Example)) {
    throw new TypeError(
      " Class constructor Example cannot be invoked without 'new'"
    );
  }
  this.name = name;
}

类通过函数简写形式写的函数方法是添加到对象原型上的,所以现在我们也是往Example的原型上添加方法,但是这里要注意的是,这个方法是不可被枚举的,也就是说,打印实例对象上的属性,是访问不到这个方法的

怎么实现呢? —— 通过 Object.defineProperty() 来设置 enumerable: false 即可 👇

// 可枚举
Example.prototype.getName = function () {
  console.log(this.name);
};

// 不可枚举
Object.defineProperty(Example.prototype, "getName", {
  value: function () {
    console.log(this.name);
  },
  enumerable: false,
});

最后一个区别比较的隐蔽,还是函数的属性方法,类的属性方法只能通过类的实例对象来调用👇

let e = new Example("test");
e.getName();
// test

如果你使用 new e.getName(), 则会报错,JS里默认所有的函数都是可以通过 new 来调用的,但是这里是个例外

怎么实现? —— 跟上面一样,通过判断 this 的指向即可

Object.defineProperty(Example.prototype, "getName", {
  value: function () {
    if (!(this instanceof Example)) {
      throw new TypeError("e.getName is not a constructor");
    }
    console.log(this.name);
  },
  enumerable: false,
});

# 最终版本

class 转为 function 的效果就是下面这些代码了👇

("use strict");
function Example(name) {
  if (!(this instanceof Example)) {
    throw new TypeError(
      " Class constructor Example cannot be invoked without 'new'"
    );
  }
  this.name = name;
}

Object.defineProperty(Example.prototype, "getName", {
  value: function () {
    if (!(this instanceof Example)) {
      throw new TypeError("e.getName is not a constructor");
    }
    console.log(this.name);
  },
  enumerable: false,
});
How to love
Lil Wayne