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

Tom*_*mSW 40 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>
Run Code Online (Sandbox Code Playgroud)

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

CMS*_*CMS 61

目前只有一个现有的东西可以实际上做你想要的,但不幸的是没有广泛实施:

目前只有两种可用的实现方式,最新的Firefox 4测试版(自FF3.7预发布以来一直存在)和服务器端JavaScript的节点代理 - ChromeSafari目前正在开发它 - .

这是一个早期的提案ECMAScript中的下一个版本,它是可以让你实现API 虚拟化的对象(代理),您可分配各种陷阱 -callbacks-,在不同的情况下被执行,你得到完全控制在这个时候 - 在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
Run Code Online (Sandbox Code Playgroud)

在这里尝试一下.

Proxy 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)
Run Code Online (Sandbox Code Playgroud)

除了提案之外,我见过的唯一资源是以下教程:

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


Paw*_*wel 7

以下是如何获得类似于__noSuchMethod__的行为

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

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

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

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);
       }
    }
});
Run Code Online (Sandbox Code Playgroud)

现在尝试一下:

myObjectProxy.existingMethod('was called here');
myObjectProxy.nonExistingMethod('with a parameter');
Run Code Online (Sandbox Code Playgroud)

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

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

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