【问题标题】:Can you make an object 'callable'?你能让一个对象“可调用”吗?
【发布时间】:2013-10-12 15:36:17
【问题描述】:

是否可以通过在其上实现callapply 或以其他方式使对象可调用?例如:

var obj = {};
obj.call = function (context, arg1, arg2, ...) {
    ...
};

...

obj (a, b);

【问题讨论】:

标签: javascript


【解决方案1】:

不,但您可以将属性添加到函数中,例如

function foo(){}
foo.myProperty = "whatever";

编辑:要“制作”一个可调用的对象,您仍然必须执行上述操作,但它可能看起来像:

// Augments func with object's properties
function makeCallable(object, func){
    for(var prop in object){
        if(object.hasOwnProperty(prop)){
            func[prop] = object[prop];
        }
    }
}

然后您只需使用“func”函数而不是对象。实际上,此方法所做的只是在两个对象之间复制属性,但是……它可能会对您有所帮助。

【讨论】:

  • 是的,但是如何复制原型链?我需要一个可调用的函数/对象,但实际上是一个类型的实例。
  • 我希望有一个符号可以设置为使对象可调用,例如 obj[Symbol.invoke] = function(args) { };
  • @NickSotiros 可能是Object.setPrototypeOf(func, object)?
  • 仅供参考:在 NodeJS 中,如果属性名称与函数对象上的只读属性(例如 name)冲突,这将失败。示例:(function(){}).name=''; TypeError: Cannot assign to read only property 'name' of function 'function(){}'
  • @NickSotiros 要使对象“可调用”,您可以在对象的构造函数中return a Proxy
【解决方案2】:

ES6 现在有更好的解决方案。如果您以不同的方式创建对象(使用classextending 'Function' 类型),您可以拥有它的可调用实例。

另请参阅:How to extend Function with ES6 classes?

【讨论】:

  • 我不会这样称呼它更好。主要浏览器更好地支持该解决方案实际上迫使人们使用该解决方案而不是替代方案。但这并没有使这个解决方案变得更好。此解决方案违反直觉,并且与其他 OOP 方法不兼容。
  • @wandalen 恐怕我不明白你想说什么。无论如何,一个更易读、更干净、(实际上)更直观(至少对于那些来自 c++ 或 java - OOP 的人来说)的解决方案更好,不是吗?为什么您认为扩展“功能”以创建可调用的类不直观?
  • 每个“类”有一个extends,所以你宁愿用它来解决语言问题,重用你可能应该在类中聚合的代码,或者应该只将它用于域对象中的自然连接?
  • 如果你也提供一个代码 sn-p 那就太好了。
【解决方案3】:

遵循@Max 的同一行,但使用Object 的ES6 扩展将对象obj 的所有属性和原型传递给可调用的func

Object.assign(func, obj);
Object.setPrototypeOf(func, Object.getPrototypeOf(obj));

【讨论】:

    【解决方案4】:

    其他人提供了当前答案(“否”)和一些解决方法。至于未来的一流支持,我向 es-discuss 邮件列表提出了这个建议。那个时候这个想法并没有走得太远,但也许一些额外的兴趣会帮助这个想法再次发生。

    https://esdiscuss.org/topic/proposal-default-object-method

    【讨论】:

      猜你喜欢
      • 2019-08-12
      • 1970-01-01
      • 2011-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-25
      • 2011-01-17
      • 1970-01-01
      相关资源
      最近更新 更多