【问题标题】:Capture method missing in Javascript and do some logic?Javascript 中缺少捕获方法并执行一些逻辑?
【发布时间】:2012-01-07 04:12:34
【问题描述】:

在 Ruby 中,您可以捕获对丢失的方法的调用并动态定义它。

我想在 JavaScript 中实现的是拥有一个没有方法的对象。我希望将缺少的方法转换为对 emit() 的调用:

app.isReady() -> app.emit("isReady")
soldier.kills() -> soldier.emit("kills")

我认为捕获丢失的方法错误并运行 emit(methodName) 比在运行时定义所有方法(来自固定列表)更好。这样,如果一个对象有成百上千个事件,我们就不会产生性能开销。

最好的方法是什么?

更新:这是一个 API 设计,所以我宁愿置身事外:

try {
  app.isReady()
} catch(e) {
  ...
}

我想知道如何在幕后完成这项工作,以便用户可以像往常一样使用方法。

【问题讨论】:

    标签: javascript porting sample method-missing reification


    【解决方案1】:

    我创建了一个 Node.js 包来处理您的情况。它叫做auto-object。

    一目了然:

    const myObject = autoObject.createObject(function(name) {
        if(name.startsWith("say")) {
            return function() {
                return name.substr(3);
            }
        }
    
        return name;
    });
    
    myObject.foo;       ///< "foo" 
    myObject.sayFoo();  ///< "Foo" 
    myObject.sayBar();  ///< "Bar" 
    

    更重要的是,这也适用于类。

    【讨论】:

      【解决方案2】:

      通过以下过程在函数指针上使用 RegExp test:

      • 将对象字面量作为参数传递
      • 将默认方法的名称作为字符串传递
      • 将回退方法的名称作为字符串传递
      • 使用下标符号取消引用函数指针
      • 使用正则表达式根据名称function 检查类型
      • 如果成功,则使用下标表示法调用默认值
      • 如果失败,则使用下标表示法调用回退

      例如:

      /* Define mapping */
      var app = {"emit": emit};
      
      /* Define interface */
      function emit(){}
      
      function \u1000missing(object, method, fallback)
        {
        /* Existence check */
        if (/function/.test(object[method]) ) 
          {
          object[method]();
          }
        /* reify */
        else
          {
          object[fallback](method)
          }    
        }
      
      \u1000missing(app,"isReady","emit")
      

      您可能会问为什么要使用下标表示法。下标符号允许动态创建属性和方法。因此,如果您曾经进行过任何类型的元编程,您很可能会使用下标符号。

      参考文献

      【讨论】:

        【解决方案3】:

        这样,如果一个对象有成百上千的事件,我们就不会产生性能开销。

        我认为认为向对象添加方法的性能开销小于将​​方法调用转换为发出调用的性能开销是一个巨大的误解。

        但是你不能在 ES5 中实现这个功能

        但是,可以使用Harmony proxies 来实现这一点。

        我建议查看simulating __noSuchMethod__。

        我相信 ES6 代理是实验性的,可以在 V8 中启用,因此您现在可以将它们与 node.js 一起使用。

        【讨论】:

        【解决方案4】:

        在这个阶段不可能始终如一地做到这一点,除非你能保证你的应用只能在 Mozilla 上运行,在这种情况下,noSuchMethod 就是你所追求的。

        据我所知,目前还没有其他浏览器实现这一点。

        【讨论】:

        • __noSuchMethod__ 在 mozilla 中可能会被弃用/删除。
        • 啊,谢谢。所以,是的,反正我们的朋友运气不好;)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-05
        • 2011-04-24
        • 2016-07-10
        相关资源
        最近更新 更多