如何在Javascript中像函数一样调用对象?

问题描述 投票:0回答:1

假设你有一个函数:

const myFunc = function () {
  console.log('Function has been invoked');
}

您可以使用括号作为

myFunc()
来调用函数。

现在假设你有一个物体。即使函数是对象,您也不能使用括号调用对象:

const myObj = {};
myObj(); // TypeError: myObj is not a function

那么有没有办法让对象像JS中的函数一样可调用?

首先我想到了函数对象具有的内部方法

[[Call]]
。我尝试自己设置此属性,但出现错误:

const myObject = {
  [[Call]]: function() {
    console.log("My object was invoked!");
  }
};
// ReferenceError: Call is not defined

然后我读到,在 EcmaScript 中无法自行配置此属性,因此无法访问和更改对象的此内部属性。

接下来我想到了Proxy,它有

apply()
陷阱来捕获函数对象的
[[Call]]
方法。我尝试设置代理,但仍然出现错误:

const callableObject = new Proxy({}, {
  apply: function() {
    console.log("Callable object was invoked!");
  }
});

callableObject(); // TypeError: callableObject is not a function

我尝试过改变原型链,让对象的原型是Function.prototype,但还是不行:

const obj = {};
Object.setPrototypeOf(obj, Function.prototype)
const callableObject = new Proxy(obj, {
    apply: function() {
        console.log("Callable object was invoked!");
    }
});
  
callableObject(); // TypeError: callableObject is not a function

好像Proxy可以做到这一点,但我还是想不出办法。

我看到的唯一可能性就是首先创建一个函数,然后将其视为对象,然后在需要时调用它。

javascript function properties prototype prototype-chain
1个回答
0
投票

函数本身就是一个对象:

console.log(Object.getPrototypeOf(Function.prototype).constructor.name);

const obj = function(){};
obj.prop = 'test';

console.log(obj.prop);

所以你可以直接将函数用作对象,但要小心函数的 props,如

name
length
等。

由于您的语法非常灵活,超越了

const obj = {}
并允许使用代理,因此您可以代理函数,但将道具单独保存在专用对象中。所以代理函数将是对象的访问器:

const obj = {};

const callableObject = new Proxy(new Function, {
  apply() {
    console.log("Callable object was invoked!");
  },
  get(_, prop){
    return Reflect.get(obj, prop);
  },
  set(_, prop, val){
    Reflect.set(obj, prop, val);
  }
});

callableObject();

callableObject.prop = 'test';

console.log(callableObject.prop, obj.prop);

© www.soinside.com 2019 - 2024. All rights reserved.