JS如何用标准原型方法实现兼具静态方法与实例创建能力的类?
需求说明
需要实现同时支持静态方法定义、实例创建的类,所有逻辑封装在独立命名空间中,采用标准原型实现方案,同时确认该类实现方式是否为良好实践。
额外要求:避免直接通过函数名引用类本身,降低10个以上静态方法场景下的维护成本。
现有实现存在的问题
你提供的两个示例存在明显逻辑缺陷:
- 构造函数内部每次执行都会重写prototype对象,会导致不同时机创建的实例原型链不统一,原型链上的方法共享特性失效
- 构造函数默认不传参时返回构造函数本身的设计,会导致首次调用初始化类时this指向异常(非严格模式下指向全局,严格模式下为undefined),同时每次创建实例都会重复执行静态方法、原型方法的定义逻辑,产生不必要的性能开销
优化实现方案
直接将类声明、静态方法定义、原型方法定义的逻辑拆分到构造函数外部,通过局部变量引用构造函数即可避免重复写类名:
var MyNamespace = (function() { // 构造函数仅处理实例初始化逻辑 function MyClass(e) { this.e = e; } // 用局部变量引用构造函数,后续修改类名仅需改此处和构造函数声明两处 const cls = MyClass; // 批量定义静态方法,不需要重复写类名 cls.staticMethod1 = function() {}; cls.staticMethod2 = function() {}; // 更多静态方法直接加即可 // 定义原型方法,用Object.assign避免覆盖原型默认的constructor指向 Object.assign(cls.prototype, { instanceMethod1: function() {}, instanceMethod2: function() {} }); // 偏好Object.defineProperties写法可替换为如下逻辑,效果一致 // Object.defineProperties(cls, { // staticMethod1: { value: function() {} } // }); return { MyClass: MyClass }; })(); // 使用示例 // 调用静态方法 MyNamespace.MyClass.staticMethod1(); // 创建实例 const instance = new MyNamespace.MyClass('test'); instance.instanceMethod1();
方案说明
- 该实现是ES6 class语法普及前的行业标准实现方案,属于良好实践,ES6 class本质上就是该实现的语法糖,底层逻辑完全一致
- 逻辑拆分清晰,构造函数仅处理实例初始化,静态方法、原型方法定义仅在命名空间初始化时执行一次,没有冗余性能开销
- 维护成本低,需要修改类名时仅需修改构造函数声明、cls变量赋值两处即可,所有静态方法、原型方法的引用都复用cls变量,不需要全局替换
- 完全符合命名空间隔离要求,所有逻辑都在IIFE的独立作用域内,不会污染全局作用域
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

