Метод захвата отсутствует в Javascript и немного логики? - PullRequest
4 голосов
/ 27 ноября 2011

В Ruby вы можете перехватить вызов метода, который отсутствует и определить его на лету.

То, чего я хочу достичь в JavaScript, - это иметь объект без методов.Я хочу, чтобы отсутствующий метод был переведен в вызов emit ():

app.isReady() -> app.emit("isReady")
soldier.kills() -> soldier.emit("kills")

Я думаю, что лучше зафиксировать ошибку отсутствующего метода и запустить emit (methodName), а не определять все методы (из фиксированногосписок) во время выполнения.Таким образом, мы не теряем производительность, если для объекта существуют сотни или тысячи событий.

Каков наилучший способ сделать это?

ОБНОВЛЕНИЕ: Это проект API, поэтомуЯ предпочитаю держаться подальше:

try {
  app.isReady()
} catch(e) {
  ...
}

Я хочу знать, как я могу добиться этого за сценой, чтобы пользователи могли использовать методы, как обычно.

Ответы [ 4 ]

6 голосов
/ 27 ноября 2011

Таким образом, мы не теряем производительность, если для объекта существуют сотни / тысячи событий.

Я думаю, что это серьезное заблуждение думать, что накладные расходы на производительность при добавлении методов к объекту меньше, чем накладные расходы на преобразование вызовов методов в вызовы emit.

Однако вы не можете реализовать эту функцию в ES5

Однако можно реализовать это с помощью прокси-серверов Harmony .

Я рекомендую посмотреть на имитацию __noSuchMethod__.

Я полагаю, что прокси-серверы ES6 являются экспериментальными и могут быть включены в V8, чтобы вы могли использовать их сегодня с node.js.

2 голосов
/ 27 ноября 2011

Невозможно сделать это последовательно на этом этапе, если только вы не можете гарантировать, что ваше приложение будет работать только на Mozilla, и в этом случае noSuchMethod - это то, что вам нужно.

Насколько я знаю, ни один из других браузеров пока не реализует это.

0 голосов
/ 17 июня 2017

Я создал пакет Node.js для решения вашей ситуации. Он называется автообъект .

Вот взгляд:

const myObject = autoObject.createObject(function(name) {
    if(name.startsWith("say")) {
        return function() {
            return name.substr(3);
        }
    }

    return name;
});

myObject.foo;       ///< "foo" 
myObject.sayFoo();  ///< "Foo" 
myObject.sayBar();  ///< "Bar" 

Более того, это работает и с классом.

0 голосов
/ 04 апреля 2014

Используйте RegExp test для указателя на функцию, используя следующий процесс:

  • передать литерал объекта в качестве аргумента
  • передать имя метода по умолчанию в виде строки
  • передать имя резервного метода в виде строки
  • Использование индексной нотации для разыменования указателя функции
  • используйте регулярное выражение для проверки типа по имени function
  • в случае успеха вызовите значение по умолчанию, используя нижнюю запись
  • в случае сбоя вызовите резервный вариант, используя нижнюю запись

Например:

/* Define mapping */
var app = {"emit": emit};

/* Define interface */
function emit(){}

function \u1000missing(object, method, fallback)
  {
  /* Existence check */
  if (/function/.test(object[method]) ) 
    {
    object[method]();
    }
  /* reify */
  else
    {
    object[fallback](method)
    }    
  }

\u1000missing(app,"isReady","emit")

Вы можете спросить, почему вы хотите использовать индексную запись. Индексная запись позволяет динамически создавать свойства и методы. Так что, если вы когда-нибудь будете выполнять какие-либо метапрограммирования, вы, скорее всего, будете использовать индексную запись.

Ссылки

...