views:

121

answers:

3

I want to define a behavior on Javascript objects that kicks in when the referenced attribute/method doesn't exist. In Lua you can do this with metatables and the __index & __newindex methods.

--Lua code
o = setmetatable({},{__index=function(self,key)
  print("tried to undefined key",key)
  return nil
end
})

So I'm wondering if there is something similar in javascript.

What I'm trying to achieve is a generic RPC interface that works like this (not valid Javascript):

function RPC(url)
{
    this.url = url;
}

RPC.prototype.__index=function(methodname) //imagine that prototype.__index exists
{ 
    AJAX.get(this.url+"?call="+ methodname);
}

var proxy = RPC("http://example.com/rpcinterface");
proxy.ServerMethodA(1,2,3);
proxy.ServerMethodB("abc");

So how can I do this?

Can this even be done?

A: 

I assume your actual need is more complicated than the example, because you're doing nothing with the parameters you're passing to ServerMethodA and ServerMethodB, and otherwise you would just do something like

function RPC(url)
{
    this.url = url;
}

RPC.prototype.callServerMethod = function(methodname, params)
{ 
    AJAX.get(this.url+"?call="+ methodname);
}

var proxy = RPC("http://example.com/rpcinterface");
proxy.callServerMethod("ServerMethodA", [1,2,3]);
proxy.callServerMethod("ServerMethodB", "abc");
Tim Down
+2  A: 

javascript is more like scheme than it is like smalltalk (which supports method not defined) or lua. Unfortunately your request is not supported to the best of my knowledge.

You could emulate this behaviour with an extra step.

function CAD(object, methodName) // Check and Attach Default
{
    if (!(object[methodName] && typeof object[methodName] == "function") &&
         (object["__index"] && typeof object["__index"] == "function")) {
        object[methodName] = function() { return object.__index(methodName); };
    }
}

so your example becomes

function RPC(url)
{
    this.url = url;
}

RPC.prototype.__index=function(methodname) //imagine that prototype.__index exists
{ 
    AJAX.get(this.url+"?call="+ methodname);
}

var proxy = RPC("http://example.com/rpcinterface");
CAD(proxy, "ServerMethodA");
proxy.ServerMethodA(1,2,3);
CAD(proxy, "ServerMethodB");
proxy.ServerMethodB("abc");

more functionality could be implemented in CAD but this gives you the idea...you could even use it as a calling mechanism that calls the function with arguments if it exists, bypassing the extra step I introduced.

barkmadley
I kinda imagined that javascript had an __index, and that i just couldn't find it, but seems I was wrong. Thanks for information and trick. It's good enough for my purposes!
Robert Gould
+3  A: 

Just FYI: Firefox supports a non-standard __noSuchMethod__ extension.

Miles
thanks for the info, unfortunately I need cross-browser compatability, but nice to know, maybe others will follow suite
Robert Gould