Есть ли в прототипах Javascript что-то эквивалентное Lua __index & __newindex? - PullRequest
4 голосов
/ 29 октября 2009

Я хочу определить поведение объектов 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");

Так как я могу это сделать?

Можно ли это сделать?

Ответы [ 4 ]

4 голосов
/ 30 октября 2009

Только к вашему сведению: Firefox поддерживает нестандартное расширение __noSuchMethod__.

3 голосов
/ 29 октября 2009

JavaScript больше похож на схему, чем на smalltalk (который поддерживает метод, который не определен) или на lua. К сожалению, ваш запрос не поддерживается, насколько мне известно.

Вы можете подражать этому поведению с дополнительным шагом.

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

так что ваш пример становится

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 можно реализовать больше функциональности, но это дает вам идею ... вы даже можете использовать его как механизм вызова, который вызывает функцию с аргументами, если она существует, минуя дополнительный шаг, который я ввел.

1 голос
/ 19 июля 2018

спросил 8 лет, 8 месяцев назад

Теперь мы можем использовать «Прокси»

Прокси - JavaScript | MDN

Простой способ использования:

- код Lua

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

// С прокси в 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

набор: __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
1 голос
/ 29 октября 2009

Я полагаю, что ваша реальная потребность сложнее, чем в примере, потому что вы ничего не делаете с параметрами, которые передаете ServerMethodA и ServerMethodB, а в противном случае вы просто сделали бы что-то вроде

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