Метод захвата отсутствует в 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"
Более того, это работает и с классом.