Javascript 对于属性,是否有一种与_unosuchmethod _;功能等效的方法,或者有一种在JS中实现它的方法?

Javascript 对于属性,是否有一种与_unosuchmethod _;功能等效的方法,或者有一种在JS中实现它的方法?,javascript,Javascript,在一些javascript实现(Rhino、SpiderMonkey)中有一个noSuchMethod特性 我想知道,有没有一种方法可以为房产做类似的事情?我想编写可以在属性和方法上分派的代理类。更新:ECMAScript 6代理是可用的。基本上,如果您不需要支持IE11,您可以使用它们 代理对象允许您为基本操作定义自定义行为,如属性查找、赋值、枚举、函数调用等 使用ES6代理模拟“nosuch方法” 通过在属性访问上实现陷阱,您可以模拟非标准的\uuuuu noSuchMethod\uuuu陷

在一些javascript实现(Rhino、SpiderMonkey)中有一个noSuchMethod特性


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

更新:ECMAScript 6代理是可用的。基本上,如果您不需要支持IE11,您可以使用它们

代理对象允许您为基本操作定义自定义行为,如属性查找、赋值、枚举、函数调用等

使用ES6代理模拟“nosuch方法” 通过在属性访问上实现陷阱,您可以模拟非标准的
\uuuuu noSuchMethod\uuuu
陷阱的行为:

功能启用方法(obj){
返回新代理(obj{
获取(目标,p){
if(目标中的p){
返回目标[p];
}else if(目标的类型。\uuuuNoSuchMethod\uuuuuuu==“函数”){
返回函数(…args){
返回target.\uuuNoSuchMethod\uuuuuu.call(target,p,args);
};
}
}
});
}
//用法示例:
函数Dummy(){
this.ownProp1=“value1”;
返回enableNoSuchMethod(this);
}
Dummy.prototype.test=函数(){
log(“被调用的测试”);
};
Dummy.prototype.\uuuuNoSuchMethod\uuuuu=函数(名称,参数){
log(`没有使用${args}`调用这样的方法${name});
返回;
};
var instance=newdummy();
log(instance.ownProp1);
test();
someName(1,2);
实例xyz(3,4);

例如,doesNotExist(“a”、“b”)我认为这种元编程在javascript中是不可能的。相反,请尝试使用
\uuu noSuchMethod\uuu
功能来实现属性getter的效果。不是跨浏览器,因为它是一个


除了SpiderMonkey中的
\uuuu noSuchMethod\uuuu
之外,还有
\uuuu defineGetter\uuuuu
\uuu lookupSetter\uuuuuu

下面是如何获得类似于_nosuch方法的行为__

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

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上进行了测试

代理的创建可以自动化且不可见,即,如果您使用Factory模式构建对象。我这样做是为了创建可以直接从主线程调用内部函数的worker。多亏了这个名为代理的酷新功能,现在使用workers变得如此简单。有史以来最简单的worker实现:

var testWorker = createWorker('pathTo/testWorker.js');
testWorker.aFunctionInsideWorker(params, function (result) {
    console.log('results from worker: ', result);
});
你可以使用这个类


虽然这是一个老问题,但我今天一直在研究这个问题。我希望能够无缝集成来自另一个上下文(可能是不同的网页或服务器)的代码

从长远来看,这是一种突破,但我认为这仍然是一个有趣的概念。这些东西对于快速地将代码混合在一起非常有用(这些代码存在了很多年,埋藏在某处)

var mod=modproxy();
mod.callme.first.now('hello','world');
mod.hello.world.plot=555;
var v=mod.peter.piper.lucky.john.valueOf;
控制台日志(v);
mod.hello.world=函数(v){
警戒(五);
返回777;
};
var v=mod.hello.world('funky…');
控制台日志(v);
var v=mod.hello.world.plot.valueOf;
控制台日志(v);
mod.www.a(99);
mod.www.b(98);
函数modproxy(\uuu未找到\uuu){
var mem={};
返回newproxy();
函数getter(目标、名称、接收器、lname){
如果(名称=='valueOf'){
lname=lname.slice(1);
if(内存中的lname){
var v=mem[lname];
log(`rd:${lname}-${v}`);
返回v;
}
log(`rd(未找到):${lname}`);
返回;
}
lname+='.'+名称;
返回newproxy(()=>{},lname);
}//getter
函数设置器(obj、prop、newval、lname){
lname+='.'+prop;
lname=lname.slice(1);
log(`wt:${lname}-${newval}`);
mem[lname]=newval;
}//塞特
函数applyer(target、thisArg、args、lname){
lname=lname.slice(1);
if(内存中的lname){
var v=mem[lname];
如果(v的类型==='函数'){
log(`fn:${lname}-[${args}]`);
返回v.apply(thisArg,args);
}
返回v;
}
log(`fn(未找到):${lname}-[${args}]`);
}//阿普勒
函数newproxy(目标,lname){
target=target |{};
lname=lname | |'';
返回新代理(目标{
get:(目标、姓名、接收者)=>{
返回getter(target、name、receiver、lname);
},
set:(目标、名称、newval)=>{
返回设置器(目标、名称、newval、lname);
},
应用:(目标,此参数,参数)=>{
返回applyer(target、thisArg、args、lname);
}
});
}//代理

}//modproxy
你找到解决方案了吗?这个问题更多的是出于好奇,而不是出于需要。我试图将Rhino用作Java应用程序的脚本引擎,这涉及到为主机对象及其方法和属性创建js包装。最后,我改用Clojure,因为它使与Java的交流变得更加容易,不过顺便说一句,在Clojure中创建动态代理实际上比在Javascript中更难。相关:我还使用新的代理API在那里发布了一个答案。Brendan Eich视频似乎不再在JSConf.eu网站上提供。Chrome也有代理。虽然答案很广泛,但完全忽略了一个事实,即问题的重点是调用方法而不是访问属性!不一样。@ValeriuPaloş:我添加了一个示例,说明如何通过使用ES6代理来模拟非标准的
\uuuuuuu noSuchMethod\uuuuuu
陷阱。
myObjectProxy.existingMethod('was called here');
myObjectProxy.nonExistingMethod('with a parameter');
var testWorker = createWorker('pathTo/testWorker.js');
testWorker.aFunctionInsideWorker(params, function (result) {
    console.log('results from worker: ', result);
});
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