2015-05-28 4 views
0

Я использую функцию для создания других функций, которые будут использоваться в обработчике событий документа, поэтому подпись возвращаемых функций должна соответствовать сигнатуре возвращаемых функций обработчик событий, например. function (event, ui).Как сравнить функцию, когда функция создается в результате другой функции

Код выглядит следующим образом

function createEventHandler(refFn, additionalMods) { 
    var createdEvent = function (event, ui) { 
     // Merge the properties of additionalMods with an object { event, ui } 
     // call function with refFn and the resulting object as parameters 
    } 
    createdEvent.ready = true; 
    return createdEvent; 
} 

Я удалил код сгенерированной функции для ясности, но внутри refFn и additionalMods переменных обрабатываются внутри.

Теперь при обработке пользовательского ввода я называю следующую строку

var handler = events[i].handler.ready ? 
        events[i].handler : 
        createEventHandler(events[i].handler); 

В основном обрабатывать массив данных, что каждый имеет свойство обработчик, который является либо функцией или результатом вызова createEventHandler.

Суть в том, что если функция в массиве обработана, то передайте эту функцию «как есть», если не обработать функцию и сохранить результат, поэтому в конце все функции обработаны.

Прямо сейчас я присоединяю свойство, называемое готовым к сигналу о том, что функция была обработана, поскольку, как оказалось, нет надежного метода для получения имени функции в соответствии с this post, но это не так.

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

Я даже попытался

events[i].handler.prototype == createEventHandler().prototype 

но, конечно, это не сработало.

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

{Редактировать}

Чтобы добавить дополнительные разъяснения

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

Создатель createEventHandler также доступен пользователю через функцию API. Предположим, что пользователь вызывает evt.generate('model'), это создаст обработчик событий, который выполняет определенную работу, используя функцию createEventHandler под капотами. Если тогда вы можете позвонить evt.generate('bind'), другой будет сгенерирован, что сделает другую работу.

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

Все данные объявлены один раз, но содержимое массива разрозненно, потому что я могу написать следующее и должно работать.Я пропустил большинство других нерелевантных свойств.

var events = [ 
    { 
     event: 'pageshow', 
     handler: evt.generate('model') 
    }, 
    { 
     event: 'pagebeforeshow', 
     handler: function (params, last) { 
      // My custom handler for this case 
     } 
    } 
]; 

После обработки массива все обработчики находятся в одном формате и готовы к привязке. createEventHandler необходим во всех случаях, потому что я использую инъекцию зависимостей для подачи данных для этих параметров, поэтому в основном это «если не вызывать, а затем вызывать его и выполнять работу по вложению зависимостей», поэтому мне нужно сравнить функции.

+0

Возможно, не самый причудливый ответ, но вы всегда можете использовать список bools, по одному для каждой функции, и каждая функция переключает его как последний шаг, и вы проверяете свой список bools одновременно. – Spacemonkey

+0

Это не работает, потому что я не могу контролировать значение свойства 'handler'. Я предоставляю пользователю метод, который будет генерировать эти функции, или они пишут настраиваемый код, который должен быть обработан после. Я не могу заставить их писать код кода так, как я хочу, и что это не имеет для них никакого смысла. – devconcept

+0

Свойство '.ready', кажется, является правильным решением здесь. Что именно вам не нравится? – Bergi

ответ

1

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

Проблема с моим кодом заключается в том, что пользовательский автомобиль записывает функцию с свойством с именем ready, которое является общим именем и значением true, которое также является общим значением, и обработка завершится с ошибкой.

Возможно, пользователь не написал свойство, возможно, присутствует, потому что наследуется от его прототипа. Цель состоит в том, чтобы старался быть как можно более точным тем, что код, который вы обрабатываете, был результатом или вашими собственными функциями или нет, что в javascript почти невозможно.

Самый точный способ, который я нашел, это когда я читал около Equality comparisons and sameness, который говорит мне, что объект только равен самому себе, когда вы используете оператор равенства === и не являетесь примитивным объектом. Это

undefined === undefined => true 
null === null   => true 
"foo" === "foo"   => true 
0 === 0     => true 

Но

{a:1} === {a:1}   => false 

Таким образом, вы можете написать свойство готовы, которое равно объект и, как вы держите ссылку на этот объект все comparissons потерпит неудачу, если это свойство не было установлено тобой.

Это хорошо, но мне плохо, что у вас есть дополнительное свойство, называемое готовым со случайным объектом, просто для сравнения, может быть, есть лучший способ и да, есть.

В javascript нет классов, но есть наследование прототипа, поэтому вы можете написать функцию и использовать один из шаблонов наследования, чтобы установить эту функцию в качестве вашего предка и использовать ее для сравнения.

var parentEvent = function() {}; 
// This is the function that will be used as parent 
function createEventHandler(refFn, additionalMods) { 
    var createdEvent = function (event, ui) { 
     // Merge the properties of additionalMods with an object { event, ui } 
     // call function with refFn and the resulting object as parameters 
    } 
    //createdEvent.ready = true This is no longer necessary 

    // This is the "sharing prototype" inheritance pattern 
    createdEvent.prototype = parentEvent.prototype 
    return createdEvent; 
} 

Теперь прототип возвращаемой функции указывает на функцию, которую вы удерживаете в переменной. Затем вы можете сравнить их, используя

// Replace the property comparison with the prototype comparison 
var handler = events[i].handler.prototype === parentEvent.prototype ? 
       events[i].handler : 
       createEventHandler(events[i].handler); 

Это не подлежит сомнению, я знаю, но это достаточно хорошо для большинства случаев.

{Edit}

Спасибо, чтобы @Bergi для указания на то, что это не наследование в строгом смысле этого слова.Причиной этого является то, что большинство шаблонов наследования javascript требуют использования constructor functions, и я использую здесь заводскую функцию. Для того, чтобы сделать его работу, вы должны написать что-то вроде этого

function createEventHandler(refFn, additionalMods) { 
    // Same code as before 
    createdEvent.prototype = parentEvent.prototype 
    return new createdEvent(); 
} 

И сравнение сделано с

events[i].handler.__proto__ === parentEvent.prototype 

Обратите внимание на разницу в том, как функция возвращается муравей путь новый prototype свойство доступ , Это хорошо, когда у вас есть есть другие свойства, которые вы хотите вернуть, которые находятся в родительской функции.

+1

На самом деле вы не используете наследование здесь, вы просто изменили имя этого свойства с 'ready' на' prototype', что еще более распространено. Вы можете только надеяться, что это не будет запутано (что маловероятно). Однако +1 для идеи токена идентичности объекта! – Bergi

+0

Я позаимствовал образец из книги Javascrip Patterns Стефанова, но вы правы, наследование не работает. Проблема в том, что я не использую функции конструктора, необходимые для работы этого шаблона. Я использую фабричную функцию, которая объединяет целую цепочку прототипов. Чтобы заставить его работать, я должен использовать 'return new createdEvent();', но это не обязательно, потому что у меня нужна только личность для моих целей. +1 для комментария. – devconcept

0

Выполняется ли изменение содержимого массива events во время выполнения вашей программы, кроме замены их на преобразованные версии?

Если нет, то простое решение, это просто сделать копию обработчиков, прежде чем начать их преобразования, и использовать его для сравнения:

// keep this somewhere that you can access it later 
var origHandlers = events.map(function (e) { return e.handler; }); 

var handler = events[i].handler === origHandlers[i]  ? 
        createEventHandler(events[i].handler) : 
        events[i].handler; 
+0

Я не могу сказать, что было отредактировано – sirrocco

+0

@sirrocco Я добавил строку ** {Edit} **. Как вы могли это пропустить? – devconcept

+0

Возможно, редактирование не было одобрено в то время ... или вопрос кэширования, я не знаю, но в то время я не мог его увидеть. – sirrocco

Смежные вопросы