Javascript是否具有Ruby的method_missing功能?

use*_*291 48 javascript ruby metaprogramming

在Ruby中,我认为你可以调用一个尚未定义的方法,并捕获被调用方法的名称,并在运行时处理此方法.

Javascript可以做同样的事情吗?

Luc*_*lho 44

method_missing不适合JavaScript,因为它在Python中不存在:在两种语言中,方法只是恰好是函数的属性; 和对象通常具有不可调用的公共属性.与Ruby对比,其中对象的公共接口是100%方法.

JavaScript中需要一个钩子来捕获对缺失属性的访问,无论它们是否是方法.Python有它:看__getattr__特殊方法.

Mozilla 的__noSuchMethod__提议引入了另一种与它们混杂的语言的不一致性.

JavaScript的前进方向是代理机制(也在ECMAscript Harmony中),它更接近于用于自定义属性访问的Python协议,而不是Ruby的method_missing.

  • 请注意,Javascript语义有点不同,比Python更棘手.在Python中,`f = obj.m; f(x)`相当于`obj.m(x)`.在Javascript中,`obj.m(x)`将`this`设置为`obj`,而`f = obj.m; f(x)`则不设. (3认同)

lmm*_*des 28

您正在解释的ruby功能称为"method_missing" http://rubylearning.com/satishtalim/ruby_method_missing.htm.

这是一个全新的功能,仅在某些浏览器中出现,如Firefox(在蜘蛛猴Javascript引擎中).在SpiderMonkey中,它被称为"__noSuchMethod__" https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/NoSuchMethod

请阅读Yehuda Katz的这篇文章http://yehudakatz.com/2008/08/18/method_missing-in-javascript/,了解即将实施的更多细节.

  • Yehuda Katz的文章来自2008年.Brandon Eich一直倡导代理API [自2010年起](http://jsconf.eu/2010/speaker/be_proxy_objects.html).Mozilla提出的[\ _\_ _ noSuchMethod__](https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/noSuchMethod)API是非标准的,没有前途. (15认同)

Lin*_*eep 6

您可以使用Proxy类。

var myObj = {
    someAttr: 'foo'
};

var p = new Proxy(myObj, {
    get: function (target, methodOrAttributeName) {
        // target is the first argument passed into new Proxy, aka. target is myObj

        // First give the target a chance to handle it
        if (Object.keys(target).indexOf(methodOrAttributeName) !== -1) {
            return target[methodOrAttributeName];
        }

        // If the target did not have the method/attribute return whatever we want

        // Explicitly handle certain cases
        if (methodOrAttributeName === 'specialPants') {
            return 'trousers';
        }

        // return our generic method_missing function
        return function () {
            // Use the special "arguments" object to access a variable number arguments
            return 'For show, myObj.someAttr="' + target.someAttr + '" and "'
                   + methodOrAttributeName + '" called with: [' 
                   + Array.prototype.slice.call(arguments).join(',') + ']';
        }
    }
});

console.log(p.specialPants);
// outputs: trousers

console.log(p.unknownMethod('hi', 'bye', 'ok'));
// outputs: 
// For show, myObj.someAttr="foo" and "unknownMethod" called with: [hi,bye,ok]
Run Code Online (Sandbox Code Playgroud)

关于

您将使用p代替myObj.

您应该小心,get因为它会拦截p. 因此,p.specialPants()会导致错误,因为specialPants返回字符串而不是函数。

真正发生的事情unknownMethod相当于以下内容:

var unk = p.unkownMethod;
unk('hi', 'bye', 'ok');
Run Code Online (Sandbox Code Playgroud)

这是可行的,因为函数是 javascript 中的对象。

奖金

如果您知道所需的参数数量,则可以在返回的函数中正常声明它们。
例如:

...
get: function (target, name) {
    return function(expectedArg1, expectedArg2) {
...
Run Code Online (Sandbox Code Playgroud)