是否有相当于__noSuchMethod__属性的属性,或者在JS中实现它的方法?

时间:2010-02-15 15:07:39

标签: javascript

在某些javascript实现中有一个 noSuchMethod 功能(Rhino,SpiderMonkey)

proxy = {
    __noSuchMethod__: function(methodName, args){
        return "The " + methodName + " method isn't implemented yet. HINT: I accept cash and beer bribes" ;
    },

    realMethod: function(){
     return "implemented" ;   
    }
}

js> proxy.realMethod()
implemented
js> proxy.newIPod()
The newIPod method isn't implemented yet. HINT: I accept cash and beer bribes
js>

我在想,是否有办法为房产做类似的事情?我想编写可以在属性和方法上分派的代理类。

5 个答案:

答案 0 :(得分:62)

目前只有一件事可以实际做到你想要的,但遗憾的是没有广泛实施:

目前只有两个工作实现,在最新的Firefox 4测试版中(自FF3.7预发布以来一直存在)和node-proxy中的服务器 - 方JavaScript - ChromeSafari目前正在处理它。 -

它是early proposalsnext version of ECMAScript之一,它是一个允许您实现虚拟化对象(代理)的API,您可以在其中分配各种< em>陷阱 -callbacks-在不同的情况下执行,你可以完全控制目前的情况-in ECMAScript 3/5只有主机对象可以做。

要构建代理对象,您必须使用Proxy.create方法,因为您对setget陷阱感兴趣,我给您留下一个非常简单的示例:

var p = Proxy.create({
  get: function(proxy, name) {        // intercepts property access
    return 'Hello, '+ name;
  },
  set: function(proxy, name, value) { // intercepts property assignments
    alert(name +'='+ value);
    return true;
  }
});

alert(p.world); // alerts 'Hello, world'
p.foo = 'bar';  // alerts foo=bar

尝试here

代理API是如此新颖,甚至没有在Mozilla开发人员中心记录,但正如我所说,自Firefox 3.7预发布以来已经包含了一个有效的实现。

Proxy对象在全局范围内可用,create方法可以使用两个参数,一个handler对象,它只是一个包含名为陷阱的属性的对象想要实现,以及一个可选的proto参数,使您能够指定代理继承的对象。

可用的陷阱是:

// TrapName(args)                          Triggered by
// Fundamental traps
getOwnPropertyDescriptor(name):           // Object.getOwnPropertyDescriptor(proxy, name)
getPropertyDescriptor(name):              // Object.getPropertyDescriptor(proxy, name) [currently inexistent in ES5]
defineProperty(name, propertyDescriptor): // Object.defineProperty(proxy,name,pd)
getOwnPropertyNames():                    // Object.getOwnPropertyNames(proxy) 
getPropertyNames():                       // Object.getPropertyNames(proxy) 
delete(name):                             // delete proxy.name
enumerate():                              // for (name in proxy)
fix():                                    // Object.{freeze|seal|preventExtensions}(proxy)

// Derived traps
has(name):                                // name in proxy
hasOwn(name):                             // ({}).hasOwnProperty.call(proxy, name)
get(receiver, name):                      // receiver.name
set(receiver, name, val):                 // receiver.name = val
keys():                                   // Object.keys(proxy)

我见过的唯一资源,除了提案本身就是以下教程:

编辑:更多信息即将发布,Brendan Eich最近在JSConf.eu会议上发表了演讲,您可以在此处找到他的幻灯片:

答案 1 :(得分:6)

以下是如何获得与__noSuchMethod __

类似的行为

首先,这是一个简单的对象,有一个方法:

var myObject = {
    existingMethod: function (param) {
        console.log('existing method was called', param);
    }
}

现在创建一个代理,它将捕获对属性/方法的访问权限,并将现有对象添加为第一个参数。

var myObjectProxy = new Proxy(myObject, {
   get: function (func, name) {
       // if property or method exists, return it
       if( name in myObject ) {
           return myObject[name];
       }
       // if it doesn't exists handle non-existing name however you choose
       return function (args) {
           console.log(name, args);
       }
    }
});

现在尝试一下:

myObjectProxy.existingMethod('was called here');
myObjectProxy.nonExistingMethod('with a parameter');

适用于Chrome / Firefox / Opera。在IE中不起作用(但已经在Edge中工作)。还在移动Chrome上进行了测试。

代理的创建可以是自动的,也是不可见的,即如果您使用工厂模式来构建对象。我这样做是为了创建可以直接从主线程调用内部函数的worker。由于这个名为Proxy的酷炫新功能,使用工作人员现在可以如此简单。有史以来最简单的工人实施:

var testWorker = createWorker('pathTo/testWorker.js');
testWorker.aFunctionInsideWorker(params, function (result) {
    console.log('results from worker: ', result);
});

答案 2 :(得分:3)

我不相信这种类型的元编程在javascript中是可行的。相反,请尝试使用__noSuchMethod__功能来实现属性getter的效果。不是跨浏览器,因为它是Mozilla extension

var proxy = {
    __noSuchMethod__: function(methodName, args) {
       if(methodName.substr(0,3)=="get") {
          var property = methodName.substr(3).toLowerCase();                             
          if (property in this) {
              return this[property];
          }
       }
    }, color: "red"
 };
 alert(proxy.getColor());           

答案 3 :(得分:0)

除了SpiderMonkey中的__defineGetter__之外,还有__defineSetter____lookupGetter____lookupSetter____noSuchMethod__

答案 4 :(得分:0)

您可以使用Proxy类。

var myObj = {
    someAttr: 'foo'
};

var p = new Proxy(myObj, {
    get: function (target, propName) {
        // target is the first argument passed into new Proxy,
        // in this case target === myObj
        return 'myObj with someAttr:"' + target.someAttr 
               + '" had "' + propName 
               + '" called on it.';
    }
});
console.log(p.nonExsistantProperty);
// outputs: 
// myObj with someAttr:"foo" had "nonExsistantProperty" called on it