将普通对象转为可执行函数报错:TypeError: not a function
如何将普通对象转换为可执行函数?
嘿,这个问题我之前也折腾过,咱们先聊聊你原来的代码为啥报错,再给你几个可行的方案~
为什么你的代码会抛出TypeError?
你尝试通过修改原型链把普通对象改成"类函数",但JavaScript引擎判断一个值是否可调用,不只是看原型链,更关键的是它是否具备内部的[[Call]](调用)和[[Construct]](构造)方法。普通对象默认没有这些内部方法,哪怕你把它的原型指向Function.prototype,它依然是个普通对象,调用fn()的时候引擎就会报错:"fn is not a function"。
可行的实现方法
方法1:用Proxy给对象添加调用能力
这是最灵活的方式,通过Proxy拦截对象的apply操作,让普通对象可以像函数一样被调用:
const obj = { /* 你的普通对象属性 */ }; const fn = new Proxy(obj, { apply(target, thisArg, args) { // 这里写你想要执行的函数逻辑 console.log("function here!"); // 也可以访问原对象的属性 console.log(target); // 支持传入参数 console.log("参数:", args); } }); fn(); // 输出"function here!" fn("a", "b"); // 输出"参数: ["a", "b"]"
这种方式的好处是,原对象obj的结构完全不受影响,fn只是它的一个代理,既保留了对象的所有特性,又具备了函数的可调用性。
方法2:将对象属性合并到Function实例上
如果你不需要严格意义上把"原对象"变成函数,而是想要一个兼具对象属性和函数能力的值,可以直接创建一个Function实例,再把普通对象的属性合并进去:
const obj = { name: "MyFn", version: "1.0" }; // 创建一个可执行的Function实例 const fn = new Function('console.log("function here!")'); // 把obj的属性合并到fn上 Object.assign(fn, obj); fn(); // 输出"function here!" console.log(fn.name); // 输出"MyFn" console.log(fn.version); // 输出"1.0"
这种方式更直接,因为fn本身就是真正的Function实例,天然具备可调用能力,同时拥有原对象的所有属性。
方法3:通过构造函数继承Function(不推荐)
你也可以通过自定义构造函数让对象继承Function,但这种方式比较复杂,而且容易产生混淆,一般不推荐:
function ObjAsFunction() { Function.call(this, 'console.log("function here!")'); } ObjAsFunction.prototype = Object.create(Function.prototype); const fn = new ObjAsFunction(); fn(); // 输出"function here!"
不过这种方式在不同环境下可能有兼容性问题,而且代码可读性不如前两种方法。
内容的提问来源于stack exchange,提问作者Marcin Wanago
相关产品推荐
相关产品推荐

