2015-07-14 2 views
1

Я читаю Backbone.js исходный код для модуля событий и этот код заставил меня путать:Магистральные triggerEvents

var triggerEvents = function(events, args) { 
 
    var ev, i = -1, 
 
    l = events.length, 
 
    a1 = args[0], 
 
    a2 = args[1], 
 
    a3 = args[2]; 
 
    switch (args.length) { 
 
    case 0: 
 
     while (++i < l)(ev = events[i]).callback.call(ev.ctx); 
 
     return; 
 
    case 1: 
 
     while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1); 
 
     return; 
 
    case 2: 
 
     while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1, a2); 
 
     return; 
 
    case 3: 
 
     while (++i < l)(ev = events[i]).callback.call(ev.ctx, a1, a2, a3); 
 
     return; 
 
    default: 
 
     while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args); 
 
     return; 
 
    } 
 
};

Я задаюсь вопросом, почему мы должны определить args.length? Почему бы просто не написать так:

var triggerEvents = function(events, args) { 
 
    var ev, i = -1, 
 
    while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args); 
 

 
};

Так что главный вопрос: Почему мы должны определить args.length? Почему бы просто не использовать один while (++i < l)(ev = events[i]).callback.apply(ev.ctx, args);, чтобы заменить все call?

ответ

2

Это моя «догадка» (не зная, магистральную внутренностей) Кажется, что каждый event имеет свойство обратного вызова, которая является функция будет называться, когда event срабатывает. Например, click.

Эта функция обратного вызова может принимать различные аргументы. Количество аргументов неизвестно. Вот где args.length выйдет. Когда вы передаете только один аргумент, он будет вызывать функцию обратного вызова с этим единственным аргументом. Если вы вызываете его с 2, она будет проходить 2 аргументов, и т.д. ...

Причина, почему существует callback.call() и callback.apply() потому, что .call() передает аргументы в вызове функции «один за одним», тогда как .apply() проходит все аргументы как один массив.

Хорошее объяснение разницы между .call() и .apply() можно найти в этой статье http://hangar.runway7.net/javascript/difference-call-apply

PS: Поправьте меня, если мое предположение о Backbone неправильно :)

UPDATE

Существует комментарий в исходном коде https://gist.github.com/badsyntax/4663217, чуть выше объявления triggerEvents. Так вот твой ответ. Вы можете попытаться найти некоторые тесты парфюм :)

// Optimized internal dispatch function for triggering events. Tries to 
    // keep the usual cases speedy (most Backbone events have 3 arguments). 

UPDATE 2

Причиной этого является то, что оптимизация .call() может быть быстрее, чем .apply(), потому что .apply() потребности построить массив в качестве аргумента. (И вызов .call() и .apply почти всегда медленнее, чем вызов исходного метода, просто потому, что есть еще одна операция для выполнения)

+0

Да, '.call()' и '.apply()' имеет diffrence между способами получения аргументов, но 'args' уже является массивом, поэтому я думаю, что в этой ситуации использовать только один' .apply() 'может добиться того же эффекта, другими словами, определить' args.length' и '. call() 'не имеет никакого смысла, может быть избыточным, я думаю. – huachengzan

+0

@huachengzan Возможно, вы правы ... можете ли вы протестировать его и предоставить ссылку на результаты? –

+0

@huachengzan Я обновил свой ответ ... –

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