Если вторая подпрограмма быстрее, вероятно, потому, что она не выполняет то, что должна. Посмотрите на этот фрагмент:
for (var i=0; i < args.length; i++) {
hover_selector = $(args[i][0]);
class_name = args[i][1];
add_link = args[i][2];
hover_item = $(hover_selector)
hover_selector.each(function(){
$(this).hover(
function () {
Две проблемы здесь:
- Вы используете неявные глобальные переменные.
- Блоки в JavaScript не вводят новую область видимости.
Любой из них вызовет одну и ту же ошибку, вместе они просто вдвойне гарантируют, что это произойдет: замыкания, созданные для функций обработчика событий hover()
, содержат только значения последней итерации цикла. Когда эти обработчики будут наконец вызваны, class_name
всегда будет "selected"
, а add_link
всегда будет true
. Напротив, ваша исходная функция будет вызываться каждый раз с другим набором параметров, которые будут захвачены обработчиками событий в области действия функции и, следовательно, работать как положено.
Что касается стиля ... Это грязно. Вы заключили все тело функции в цикл, удалили описательные аргументы и значительно усложнили вызов функции.
К счастью, вы можете решить проблему, о которой я говорил выше, упростить функцию, и упростить, как она вызывается за один раз:
// For starters, I've eliminated explicit parameters completely.
// args wasn't descriptive, and all JavaScript functions have an implicit
// arguments array already - so let's just use that.
function mouse_function_three () {
// use jQuery's array iteration routine:
// this takes a function as an argument, thereby introducing scope and
// avoiding the problem identified previously
$.each(arguments, function() {
var class_name = this.class_name;
var add_link = this.add_link;
var selected = $(this.hover_selector);
// no need to use selected.each() - jQuery event binding routines
// always bind to all selected elements
selected.hover(function() {
$(this).addClass(class_name);
},
function() {
$(this).removeClass(class_name);
});
// bring this out of the hover handler to avoid re-binding
if ( add_link ) {
$(selected).click(function(){
var href = $(this).find('a').attr('href');
window.location.href = href;
});
}
}); // each set of arguments
}
Затем вы бы назвали эту новую процедуру так:
console.time('f3');
mouse_function_three(
{hover_selector: '#newsletter .right', class_name: 'hovered', add_link: true},
{hover_selector: '.block-couple div.right', class_name: 'hovered', add_link: false},
{hover_selector: '.bulletin', class_name: 'selected', add_link: true}
);
console.timeEnd('f3');
Обратите внимание, что эти изменения вполне могут устранить любую разницу в скорости по сравнению с вашей первоначальной попыткой, поскольку код фактически делает то же самое, но с дополнительным этапом упаковки и последующего извлечения параметров ...