如何创建类似Boolean对象的兼具可调用特性与可调用构造函数的类?
实现可直接调用且支持构造函数的类(类似Boolean)
要实现一个像原生Boolean那样的类——既支持直接调用类本身执行逻辑(如Boolean(1)返回true),又能通过new关键字创建实例(如new Boolean(1)生成布尔对象),同时还能挂载静态方法,以下是几种可行的实现方式:
一、普通函数基础实现
函数本身天然支持直接调用和new调用,通过new.target判断调用方式,是最直观的方案:
function MyBoolean(value) { // 判断是否通过 new 关键字调用 if (new.target) { // 构造函数逻辑:初始化实例属性 this.value = Boolean(value); } else { // 直接调用时的逻辑:返回处理后的值 return Boolean(value); } } // 给实例添加方法 MyBoolean.prototype.toString = function() { return `MyBoolean(${this.value})`; }; // 给类本身添加静态方法 MyBoolean.isTruthy = function(val) { return Boolean(val) === true; }; // 测试用例 console.log(MyBoolean(1)); // true(直接调用) console.log(new MyBoolean(1)); // MyBoolean { value: true }(实例) console.log(MyBoolean.isTruthy(0)); // false(静态方法调用)
二、ES6 类 + 函数包装实现
如果偏好ES6类的语法,可以先定义类,再用函数包装重写调用行为:
// 定义原始类 class OriginalMyBoolean { constructor(value) { this.value = Boolean(value); } toString() { return `MyBoolean(${this.value})`; } static isTruthy(val) { return Boolean(val) === true; } } // 包装成可直接调用的函数 const MyBoolean = function(value) { if (new.target) { // new 调用时返回原始类实例 return new OriginalMyBoolean(value); } else { // 直接调用时执行逻辑 return Boolean(value); } }; // 拷贝静态方法到包装函数 Object.assign(MyBoolean, OriginalMyBoolean); // 保持原型链一致,确保实例能访问类原型方法 MyBoolean.prototype = OriginalMyBoolean.prototype; MyBoolean.prototype.constructor = MyBoolean; // 测试用例 console.log(MyBoolean("hello")); // true console.log(new MyBoolean("hello")); // MyBoolean { value: true } console.log(MyBoolean.isTruthy("")); // false
三、ES6 类 + Proxy 拦截实现
利用Proxy拦截类的apply操作,实现直接调用的逻辑,代码更紧凑:
const MyBoolean = new Proxy(class { constructor(value) { this.value = Boolean(value); } toString() { return `MyBoolean(${this.value})`; } static isTruthy(val) { return Boolean(val) === true; } }, { // 拦截类的直接调用(apply 操作) apply(target, _, args) { return Boolean(args[0]); } }); // 测试用例 console.log(MyBoolean(null)); // false console.log(new MyBoolean(null)); // MyBoolean { value: false } console.log(MyBoolean.isTruthy(10)); // true
各方案特点
- 普通函数方案:兼容性最好,写法简洁,无需额外语法支持。
- ES6类+包装方案:保留类的写法习惯,需手动同步静态方法和原型链。
- Proxy方案:代码结构更紧凑,但需要环境支持Proxy(现代浏览器、Node.js 6+均支持)。
内容的提问来源于stack exchange,提问作者Aidan
相关产品推荐
相关产品推荐

