如何创建一个可以调用任何方法的JS对象?

时间:2012-03-08 07:22:34

标签: javascript

我想创建一个javascript对象,我可以调用任何方法,而不必定义它们。理想情况下,我可以将其称为函数,它将调用一个函数,我将函数的名称称为其参数。

所以我会用callMethod(methodName)方法定义一个对象,当我调用

thisObject.doAThing();

它会调用thisObject.callMethod("doAThing");

这可以在javascript中使用吗?

3 个答案:

答案 0 :(得分:1)

不,那是不可能的。如果JavaScript对象没有属性,则不能将未定义的值视为方法。

答案 1 :(得分:1)

至少在Firefox中,您可以使用魔术方法__noSuchMethod__来实现目标:

var o = {}
o.__noSuchMethod__ = function(id, args) { alert(id + args); }
o.foo(2,3) //will alert "foo" and "2,3"

请注意,这不是标准,正在考虑删除,因此it will not be added to V8

答案 2 :(得分:0)

原帖(对不起,应该在q评论中提出这个问题):

我很难看清楚这一点。如果callMethod可以在某处访问'doAThing'方法,那么为什么不能在实例化对象时或者当callMethod的源添加了新方法时将其插入?

不要试图诋毁你。只是试着看看是否可能在疯狂疯狂世界的某个地方调用/应用/原型范例,它可以适应你希望以其他方式实现的目标。

在此评论后添加了编辑:

  

我想创建一个代理对象,将其调用委托给另一个   宾语。 - msfeldstein

好的,原型可能就是答案,因为它基本上可以作为对象本身没有的方法的后备。每个函数都有一个原型属性,基本上只是一个简单的vanilla对象。当函数用作构造函数时,分配给构造函数原型的方法和属性将成为构造函数实例的后备,当您调用它们没有的属性时。您可以向该原型对象添加属性,它们将有效地用于已创建的实例。所以在关联对象的情况下,我正在考虑这样的事情:

//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非常适合的。如果您正在寻找的门面方法的任何方面我都没有在这里实现,请告诉我。