Метод захвата отсутствует в Javascript и немного логики?

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

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

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

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

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

ОБНОВЛЕНИЕ: Это дизайн API, поэтому я предпочитаю:

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

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

4 ответа

Решение

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

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

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

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

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

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

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

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

Используйте 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")

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

Рекомендации

Я создал пакет 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" 

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

Другие вопросы по тегам