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?
Update: this answer is no longer correct. ECMAScript 2015 (ECMA-262 6th Ed. §§ 9.5, 26.2) defined Proxy
objects, which can be used to achieve this.
In JavaScript engines that don't provide Proxy
, this functionality is still unavailable. In those engines, idioms which in Lua would rely on __index
and __newindex
will have to be expressed in some other way, like below.
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.