【问题标题】:Calling Objects as Functions JavaScript将对象作为函数调用 JavaScript
【发布时间】:2020-05-02 02:44:11
【问题描述】:

在 JavaScript 中,函数是对象,只是它们可以被调用和执行,这相当于在其他语言中重载对象的 () 运算符。

我可以将此功能应用于任何对象吗?

我知道没有像 [Symbol.call] 这样的属性或类似的东西。如果有类似的东西,如果你能告诉我它是什么,我将不胜感激。

如果声明对象并为它们分配属性是我的唯一选项,那没关系,但我更喜欢使用类来完成,例如 C++。

我可以做这样的事情

function func(...) {
...
}

func.foo = x,
func.bar = y;

但如果我能做更多类似的事情会更可取

const func = {

    [`()`]: function(...) {
    ...
    },
    foo: x,
    bar: y
};

【问题讨论】:

    标签: javascript function class object


    【解决方案1】:

    我可以将此功能应用于任何对象吗?“

    没有。从 ECMAScript 第 10 版 (2019) 开始,这是不可能的。

    ()-operator/expression 构造只能用于函数对象。

    这是因为它使用了[[Call]] 内部方法。 7.3.12 Call 部分表示这是为函数对象定义的,规范没有规定将[[Call]] 内部方法添加到其他对象。

    7.3.12 调用 ( F, V [ , argumentsList ] )

    抽象操作Call用于调用函数对象的[[Call]]内部方法。 [..]

    规范的编写方式使得未来的修订版可能会增加通用支持。

    无论如何,如问题所示,函数对象可以作为代理进行变异:所以继续,根据需要进行调整。

    【讨论】:

    • 谢谢!很遗憾,从 ES10 开始无法做到这一点,但这已经足够了。
    【解决方案2】:

    因此,举一个更具体的例子来说明你想要什么可能会有所帮助,但这里有一些可以复制的选项,以及更多你提到的内容。

    这就像你的第一个例子。我猜这不是你真正想要的。注意 foo 和 bar 是静态的。

    const func = Object.assign( function(in){ console.log(in, func.foo, func.bar) }, { foo: x, bar: y } );
    

    这个可能更接近你在 () 重载的类中看到的内容

    const func = ( function(in){ console.log(in, this.foo, this.bar) } ).bind({ foo: x, bar: y });
    

    或者是这样的:

    o = o => o['()'].bind(o)
    const func = o({
      "()": function(x){ console.log(x, this.foo, this.bar) },
      foo: 1,
      bar: 2
    });
    

    获取 '()' 的属性值,并将 this 绑定到对象。您还可以使用 Object.assign 将属性复制到函数中。

    其他表达方式

    const func = (x,y) => ({
      foo: x, bar: y,
      plusone: () => func(x+1,y+1)
      showfoo() { return this.foo }
    })
    

    【讨论】:

    • 所以,我实际上计划使用更像这样的东西:const func = Object.seal(Object.assign((...) => { ... }, { foo: x, bar: y }));我更喜欢Object.assign 如果我可以使用它,但 JavaScript 初学者和遗留编码人员告诉我它可以编写代码“可读性较差”,我丢弃了他们的 cmets。我是来问的,因为我的最终目标是为此开设一门课。如果构造函数有返回值,则属性全部替换为返回值。您对如何实现这一目标有任何想法吗?我猜包装函数可以工作。
    • 你的意思是扩展原型,所以新实例将“继承”添加的属性?带有前后的代码示例将有助于了解您的需求
    【解决方案3】:

    您可以执行类似的操作,例如在外部 IIFE 函数中,返回不同类型的对象格式数据。 IIFE 可以作为参数传递给模块化脚本文件中的另一个函数,其中controller 的返回数据可以通过点符号controllerAsParameter.dostuffcontrollerAsParameter.getNumbers.percentage 获得。

    根据您的上一个示例,我的解释是否正确,您正在追求这样的事情?

    const controller = (function() {
    
        return {
            doStuff: function() {
               data.everything.forEach(function(foo) {
                   foo.calculateStuff(data.totals.bar);
            });
        },
    
        getNumbers: function() {
            return {
                abc: data.abc,
                totalDef: data.totals.def,
                totalGhi: data.totals.ghi,
                percentage: data.percentage
            }
          }
       }
    })();
    

    【讨论】:

    • 我的目标是仍然能够做到controller(),这是你的例子所不允许的。
    • @JadenGarcia 您可以将 const 控制器作为参数传递给另一个函数,然后在那里访问它的返回对象。例如。 init( controller ) 函数本身类似于 let init = ( ctrl ) => { }。然后在 init() 中,您可以使用ctrl.doStuff 访问controller.doStuff。这种方法行得通吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多