如何创建一个可以调用任何方法的JS对象
How can i create a JS Object that I can call any method on?
我想创建一个javascript对象,我可以对其调用任何方法,而无需定义它们。理想情况下,我可以把它当作一个函数来调用,它会调用我定义的一个函数,该函数的名称作为它的参数。
所以我会用callMethod(methodName)
方法定义一个对象,当我调用时
thisObject.doAThing();
它将调用thisObject.callMethod("doAThing");
这在javascript中可能吗?
不,这是不可能的。如果JavaScript对象没有属性,则不能将未定义的值视为方法。
至少在Firefox中,您可以使用神奇的方法__noSuchMethod__
来实现您的目标:
var o = {}
o.__noSuchMethod__ = function(id, args) { alert(id + args); }
o.foo(2,3) //will alert "foo" and "2,3"
请注意,这不是标准配置,正在考虑删除,因此不会将其添加到V8中。
原始帖子(对不起,应该在q评论中问这个问题):
我很难理解要点。如果callMethod在某个地方可以访问"doAThing"方法,为什么不能在对象的实例化时或者每当callMethod的源添加了新方法时插入它呢?
不是想纠缠你。只是想看看在调用/应用/原型范式的疯狂世界中,是否有可能以其他方式实现你希望实现的目标。
编辑添加在此评论后:
我想创建一个代理对象,将其调用委托给另一个对象。–msfeldstein
好吧,原型可能就是答案,因为它基本上充当了对象本身没有的方法的后备。每个函数都有一个原型属性,基本上只是一个普通的对象。当函数用作构造函数时,当您调用构造函数实例上没有的属性时,分配给构造函数原型的方法和属性将成为构造函数实例的后备。您可以将属性添加到原型对象中,这些属性将有效地提供给已经创建的实例。因此,在关联对象的情况下,我想这样做:
//A js constructor is just a function you intend to invoke with the 'new' keyword
//use of 'this.property' will make that property public in the instance
//var effectively makes it private
//Constructors funcs differ from classes in that they don't auto-handle inheritance down to other constructors. You have to come up with a prototype merging scheme to do that.
function MyFacadeConstructor(){ //expected args are objects to associate
var i = arguments.length; //arguments is a collection of args all funcs have
while(i--){
var thisObj = arguments[i];
associateObjMethods(thisObj);
}
//makes it public method but allows function hoisting internally
this.associateObjMethods = associateObjMethods;
function associateObjMethods(obj){
for(var x in obj){
if(obj[x].constructor.name === 'Function'){ //normalize for <= IE8
MyFacadeConstructor.prototype[x] = obj[x];
//or if we literally want the other method firing in its original context
//MyFacadeConstructor.prototype[x] = function(arg){ obj[x](arg); }
//Not sure how you would pass same number of arguments dynamically
//But I believe it's possible
//A workaround would be to always pass/assume one arg
//and use object literals when multiple are needed
}
}
}
}
function FirstNameAnnouncer(){
this.alertFirst = function(){
alert('Erik');
}
}
var fNamer = new FirstNameAnnouncer();
var newFacade = new MyFacadeConstructor(fNamer);
//newFacade.alertFirst should work now;
newFacade.alertFirst();
//but we can also associate after the fact
function LastNameAnnouncer(){
this.alertLast = function(){ alert('Reppen'); }
}
var lNamer = new LastNameAnnouncer();
newFacade.associateObjMethods(lNamer);
//now newFacade.alertLast should work
newFacade.alertLast();
现在,如果你想让调用对象的上下文起作用,我推荐一个事件驱动的接口,这是JS非常适合的。如果你正在寻找的facade方法有任何方面我没有在这里实现,请告诉我。
您可以使用Proxy对象拦截任何方法调用。
function proxifyMethodCalls(obj) {
const handler = {
get(target, prop, receiver) {
return function (...args) {
console.log(`Intercepted '${prop}' with arguments ${JSON.stringify(args)}`);
target.callMethod(prop);
};
}
};
return new Proxy(obj, handler);
}
let obj = {
callMethod: (methodName) => {
console.log(`'callMethod' called with '${methodName}'`);
}
};
obj = proxifyMethodCalls(obj);
obj.doAThing(true);
- 有没有任何方法可以将控制器从文件加载到ui路由器$stateProvider中
- 是否有任何方法可以使用jQuery替换在数组中定义值的文本
- 在D3.js中,有没有任何方法可以将x和y方向上的滚动事件绑定到平移svg
- 有没有任何方法可以使用node-js从不同的机器打开浏览器
- PhantomJS - 检查javascript函数是否正在运行的任何方法
- 任何一种简单的方法都可以将带有onload的元素作为目标
- 有没有一种方法可以使用任何浏览器扩展整个dom树'的开发工具
- 在不重新加载的情况下更改标头URL的任何方法
- 使用jQuery.css()方法时,是否需要转义任何字符
- Javascript集:任何覆盖元素之间比较的方法
- 在离子2中,有任何方法可以将涡旋动量作为一个事件来检测
- 有没有任何方法可以将javascript对象从源代码传递到系统/浏览器剪贴板
- 任何编写文本文件并将其替换为上一个文本文件的方法
- 是否有任何内置方法可以更改JavaScript对象'的属性设置为某个值
- 在jquery中是否有任何方法或位置可以编写从Dom中删除页面后调用的方法
- 有没有任何情况下,一个方法不应该是原型方法
- 崇高的jslint:任何忽略特定代码段的方法
- 使用多功能框在 chrome 扩展程序中包含内联自动填充功能的任何方法
- 识别值是否与 jqGrid 数据中的任何键匹配的正确方法是什么?
- 在 1 个方法中增加变量值会触发另一个方法的 for 循环,欢迎任何建议