Do Javascript prototypes have something equivalent to Lua __index & __newindex?

I want to define a behavior on Javascript objects that fires when a reference attribute / method does not exist. In Lua, you can do this with metatables and __index & __newindex .

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

So I am wondering if there is something similar in javascript.

What I'm trying to achieve is a generic RPC interface that works like this (invalid 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 be done?

+4
source share
4 answers

Update : this answer is no longer correct. ECMAScript 2015 ( ECMA-262 6th ed. §§ 9.5, 26.2) has identified Proxy objects that can be used to achieve this.

In JavaScript engines that do not provide Proxy , this functionality is still not available. In these engines, the idioms that Lua will rely on __index and __newindex will have to be expressed in a different way, as shown below.


JavaScript looks more like a scheme than it does with smalltalk (which supports a method that is not defined) or lua. Unfortunately, your request is not supported as far as I know.

You can imitate this behavior 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"); 

it would be possible to implement more functions in CAD, but this gives you an idea ... you can even use it as a call mechanism that calls a function with arguments if it exists, bypassing the extra step that I presented.

+3
source

Just a note: Firefox supports the __noSuchMethod__ custom extension.

+5
source

asked 8 years, 8 months ago

Now we can use the "Proxy"

Proxies - JavaScript | MDN

Easy way to use:

--Lua code

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

// With proxy in Javascript

 let o = new Proxy({}, { get: function (target, key, receiver) { if (!target.hasOwnProperty(key)){ console.log("tried to undefined key "+key); } return Reflect.get(target, key, receiver); }, set: function (target, key, value, receiver) { console.log('set '+ key); return Reflect.set(target, key, value, receiver); } }) 

get: __ index

set: __newindex

Reflect.get: rawget

Reflect.set: rawset

in console:

 let o= new Proxy({},{ get: function (target, key, receiver) { let ret = Reflect.get(target, key, receiver); if (!target.hasOwnProperty(key)){ console.log("tried to undefined key "+key); } return ret; } }) >> undefined oa >> VM383:5 tried to undefined key a >> undefined oa = 1 >> 1 oa >> 1 
+2
source

I assume that your real need is more complex than the example, because you do nothing with the parameters that you pass to ServerMethodA and ServerMethodB , and otherwise you 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"); 
+1
source

All Articles