2013-06-04 5 views
1

У меня есть 3 запросов о выполнении селектора:JQuery производительность селектор выдает

во-первых, есть ли разница в производительности в следующих утверждений:

$('#content .someclass') и $('.someclass', '#content')

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

Во-вторых, если бы я добавил div.someclass, это было бы лучше, чем просто .someclass (если все элементы someclass будут divs в любом случае). Я бы подумал, что первый в этом случае будет медленнее, так как он должен получить все divs сначала, а затем с .someclass, но поскольку я не уверен, как работают селекторы, я только догадываюсь

Наконец, если я использую $(this), было бы лучше кэшировать этот объект - var $thisobject = $(this) или нет никакой разницы? Я всегда думал, что $(this) был объект JQuery в его собственном праве, но теперь я думаю, что это на самом деле преобразования this в объект JQuery поэтому, возможно, приклеить ее в переменную будет лучше, чем вызов множественным $(this)

+0

Второе - недокументированное использование метода '$()'. Аргумент контекста должен быть элементом, объектом jQuery или документом. –

+0

Вы пробовали выполнять какие-либо тесты производительности, например, на jsPerf.com? – j08691

+0

нет, я не знал ни одного тестера производительности. Я поеду – Pete

ответ

1

Существует третий выбор в дополнение к двум вы перечислили:

1: $('#content .someclass') 

2: $('.someclass', '#content') 

3: $('#content').find('.someclass') 

Одна вещь, которую мы можем определенно сказать, без выполнения каких-либо тестов, что # 3 быстрее, чем # 2. Это потому, что # 2 превращается в # 3 внутри. Вот jQuery source code, который делает это. Он находится в функции init(), которая действительно является конструктором jQuery. После довольно продолжительной серии тестов, он обнаруживает, что вы назвали $(selector,context) и делает $(context).find(selector) вызов вместо:

// HANDLE: $(expr, context) 
// (which is just equivalent to: $(context).find(expr) 
} else { 
    return this.constructor(context).find(selector); 
} 

Вы могли бы сделать что $(context).find(selector) назвать себя и избежать дополнительных проверок.

Так что # 2 никогда не является самым быстрым кодом; # 3 всегда будет бить.

Также как @KevinB указывает, # 2 является not a documented use$/jQuery функция.Это может быть просто недосмотр в документах, поскольку это простое преобразование в # 3, которое является документированным использованием функции, и код работал таким образом в течение многих лет.

В любом случае, вряд ли есть какая-либо причина когда-либо использовать # 2 даже в своих документально подтвержденных случаях, так как № 3 быстрее и понятнее.

Как №3 сравнить с # 1? Вероятно, быстрее в большинстве случаев, но он может варьироваться в зависимости от браузеров, а также от отдельных селекторов и сложности страниц. jsPerf - ваш друг здесь, но обязательно укажите ему страницу, похожую на ту, что имеет значение, а не только надуманный тест.

То же самое для div.someclass против .someclass. Проверьте его и посмотрите.

Относительно $(this), что имя функции иногда делает вещи похожими на магии, когда они просто обычные вызовы функций JavaScript. В целях понимания, попробуйте использовать имя jQuery функции вместо:

jQuery(this) 

Теперь должен быть более понятно, что это действительно вызов функции, а не какое-то волшебный синтаксиса. Это то же самое, когда вы используете $(this) или $(anything): это всегда вызов функции. Так что да, если вы используете его несколько раз, это хорошая идея, чтобы сохранить результат в переменной:

var $this = $(this); 

Мое единственное предложение было бы не назвать переменную $thisobject. Дополнительное object verbiage на самом деле не делает имя более понятным; простой $this будет более знаком другим разработчикам. Или, возможно, лучше использовать более описательное имя, например.

var $element = $(this); 

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

Рассмотрим этот надуманный JQuery плагин:

jQuery.fn.log = function() { 
    this.each(function() { 
     console.log(this); 
    }); 
    return this; 
}; 

В этой короткой функции, this смысл меняется дважды: во-первых, это объект JQuery, а затем это отдельный элемент из этого объекта, а затем это объект JQuery снова , Неудивительно, что у людей есть проблемы с this!

Вместо этого, вы можете использовать именованные параметры .each():

$.fn.log = function() { 
    this.each(function(i, element) { 
     console.log(element); 
    }); 
    return this; 
}; 

Это гораздо менее запутанной, и если вам нужен объект JQuery для element во внутренней функции вы можете сделать это так же, как вы бы с this:

var $element = $(element); 
+0

Очень хороший ответ, спасибо! – Pete

+0

Мое удовольствие, рад, что это было полезно. –

1

Это зависит от точного характер селектора.

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

AIUI, браузеры, как правило, работают с «справа налево» в селекторе, так что было бы найти все элементы с классом .someclass и затем фильтровать результаты к тем, которые являются потомками #content.

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

Другими словами, «это зависит». Попробуйте на реальной странице или на jsperf.com и посмотрите, что произойдет.

1

что-то еще не упоминается в том, что там будет разница между браузерами. в браузерах, которые не поддерживают querySelectorAll, изменения стратегии. например, если браузер поддерживает этот метод, то что-то вроде $('#id').find(' > li > a'), вероятно, будет очень быстрым ... в браузере, который не работает (прежний IE, особенно), вам может быть лучше с чем-то вроде $('#id').children('li').children('a').

+0

Я думаю, что это просто IE 6, я считаю, 7 поддерживает querySeletorAll. Я знаю, что 8. –

+0

IE7 не http://caniuse.com/#search=querySelectorAll – momo

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