Javascript原型有没有类似于Lua的__index和__newindex的功能?

我想在 Javascript 对象上定义一个行为,当引用的属性/方法不存在时触发。

在 Lua 中,您可以使用元表和 __index & __newindex 方法来实现这一点。

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

所以我想知道在 Javascript 中是否有类似的东西。

我想实现的是一个通用的 RPC 接口,它的工作方式如下 (不是有效的 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");

那么我该如何实现这个目标呢?

这可以做到吗?

原文链接 https://stackoverflow.com/questions/1642167

点赞
stackoverflow用户96100
stackoverflow用户96100

我认为你的实际需求比例子更复杂,因为你传递给 ServerMethodAServerMethodB 的参数并未被使用,否则你可以这样做:

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");
2009-10-29 11:21:02
stackoverflow用户193748
stackoverflow用户193748

更新: 这个答案已经不正确了。ECMAScript 2015 (ECMA-262第六版§§ 9.5、26.2)定义了Proxy对象,可以用它来实现这个功能。

在不提供Proxy的JavaScript引擎中,这个功能仍然不可用。在这些引擎中,Lua中依赖于__index__newindex的惯用法必须以其他方式表示,例如下面所示。


JavaScript更像是Scheme,而不是支持未定义方法的Smalltalk(支持未定义方法)或Lua。不幸的是,据我所知,您的请求不受支持。

您可以用一个额外的步骤来模拟这个行为。

function CAD(object, methodName) //检查并附加默认
{
    if (!(object[methodName] && typeof object[methodName] == "function") &&
         (object["__index"] && typeof object["__index"] == "function")) {
        object[methodName] = function() { return object.__index(methodName); };
    }
}

所以您的示例变成了

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");

更多功能可以在CAD中实现,但这给了您一个想法......您甚至可以将其用作调用机制,如果存在函数,则调用带有参数的函数,绕过我介绍的额外步骤。

2009-10-29 12:59:15
stackoverflow用户64474
stackoverflow用户64474

只是提醒一下:Firefox支持一种非标准 __noSuchMethod__ 扩展。

2009-10-30 09:22:02
stackoverflow用户6676492
stackoverflow用户6676492

问题来源:发布于8年8个月前
现在我们可以使用 'Proxy'

Proxy - JavaScript | MDN

下面是一种简单的用法:

--Lua 代码

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

//在 JavaScript 中使用 Proxy

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

在控制台中:

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

o.a
>> VM383:5 tried to undefined key a
>> undefined

o.a = 1
>> 1

o.a
>> 1
2018-07-19 03:10:50