将ES6的class转换为Function

 class Person {
   constructor(name) {
     this.name = name;
   }
   sayHi() {
     console.log('hi', this.name);
   }
}

一般来说,第一反应的结构是这样的:

function Person(name) {
  'use strict';
  this.name = name;
}

Person.prototype.sayHi = function() {
  'use strict';
  console.log('hi', this.name);
};

这样肯定能用,但是如果考虑到class的某些区别于function的特性,就需要一些细节进行补充

  1. class 不可 直接执行,前面必须有new关键字,不然怎么缓解Function的二义性呢

  2. class的方法不可遍历,for in 循环只能拿到其初始化的属性,不能拿到其方法名

  3. 与1正好相反,原型方法是不能new的:new Person.prototype.sayHi()

改造如下

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

Object.defineProperty(Person.prototype, 'sayHi', {
  value: function () {
    'use strict';
    if (new.target) {
      throw TypeError('sayHi is not a constructor');
    }
    console.log('hi', this.name);
  },
  enumerable: false,
  writable: true,
  configurable: true
});

测试代码:Deno 2.6.8

Deno.test('完美的ES6 class 转 构造函数', () => {
  console.time('耗时');
  const p = new Person();
  //   Person(); 无法直接使用
  //   new Person.prototype.sayHi(); 报错
  for (const k in p) {
    console.log(k); // 没有方法名
  }
  console.timeEnd('耗时');
});