Об изменениях в jQuery 1.4 по сравнению с предыдущей версией
Июнь 20th, 2012 Archi
На днях вышла новая версия популярной JavaScript-библиотеки jQuery, она пополнела почти на 13 КБ минимизированного кода. Что же даст нам этот прирост в весе?
Значительное увеличение скорости исполнения популярных методов
Многие из часто используемых методов jQuery были в значительной степени изменены в jQuery 1.4. При анализе кода мы обнаружили, что мы могли бы значительно улучшить производительность jQuery: мы заметили, что в библиотеке выполняется слишком много вызовов внутренних функций, и решили поработать над упрощением кода.
В jQuery 1.4 мы значительно снизили сложность наиболее популярных методов. Полная информация об их производительности находится ниже по тексту.
Простые функции установки значений (setter)
Теперь вы можете передать функцию в качестве аргумента в метод .attr(), и возвращаемое этой функцией значение будет установлено в качестве соответствующего атрибута. Возможность установки значений с помощью функций реализована во следующих методах: .css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .before(), .after(), .replaceWith(), .wrap(), .wrapInner(), .offset(), .addClass(), .removeClass() и .toggleClass().
Кроме того, для следующих функций, в качестве второго параметра функции передается текущее значение: .css(), .attr(), .val(), .html(), .text(), .append(), .prepend(), .offset(), .addClass(), .removeClass() и .toggleClass().
Например, можно написать так:
1
// найти все амперсанды в тегах A и обернуть тегом span
2
$('a').html(function(i,html){
3
returnhtml.replace(/&/gi,'<span>&</span>');
4
});
5
6
// Добавить какую-либо информацию к тегам A
7
$('a[target]').attr("title", function(i,title){
8
returntitle + " (Opens in External Window)";
9
});
Атрибуты (Attributes)
Улучшена производительность функций .css() и .attr().
Возможность установки значений в методе .attr() с помощью функций
Кроме использования функций для установки значений в методе .attr(), вы также можете использовать текущее значение атрибута в этой функции.
Теперь метод .text() работает с текстом и узлами CDATA
Ядро (Core)
Быстрое создание элементов
Теперь, когда вы создаете единственный элемент с помощью функции jQuery, вы можете передать в неё объект с атрибутами и событиями элемента:
01
jQuery("<div/>", {
02
id: "foo",
03
css: {
04
height: "50px",
05
width: "50px",
06
color: "blue",
07
backgroundColor: "#ccc"
08
},
09
click: function() {
10
$(this).css("backgroundColor", "red");
11
}
12
}).appendTo("body");
Ключами этого объекта являются функции, которые будут вызваны при создании элемента, в качестве значений ключа указывается первый аргумент для функций.
.eq(-N), .get(-N)
Теперь вы можете передать отрицательные значения в методы .get() и .eq(). Например, вы можете выбрать второй с конца блок div или получить доступ к элементу DOM следующим образом:
1
$("div").eq(-2);
2
$("div").get(-2);
Новые функции .first() и .last()
Для удобства предусмотрены простые функции .first() и .last(), аналогичные .eq(0) и .eq(-1) соответственно.
Новый метод .toArray()
.get() возвращает массив из набора jQuery. Для большей ясности в jQuery 1.4 вы можете использовать метод .toArray() для достижения того же эффекта. Однако, в отличие от .get() метод .toArray() не имеет.
jQuery() возвращает пустой набор
В jQuery 1.3 метод jQuery() возвращал набор jQuery, содержащий только элемент document. В jQuery 1.4 он возвращает пустой набор jQuery. Это может быть полезно для создания пустого набора и динамического добавления в него элементов. Примечание: Метод jQuery().ready() также работает в версии 1.4, но он устарел. Пожалуйста, используйте jQuery(document).ready() или jQuery(function(){}).
jQuery(“TAG”)
Увеличена скорость обращения к элементам при передаче единственного тега.
jQuery(“<div>”), jQuery(“<div/>”) и jQuery(“<div></div>”)
При вызове всех трёх функций для создания элементов используется функция document.createElement, что привело к увеличению производительности метода jQuery("<div></div>"). Обратите внимание, что если вы указываете атрибуты в передаваемых элементах, то используется метод innerHTML.
CSS
Производительность метода .css() увеличена в 2 раза.
Производительность методов .addClass(), .removeClass() и .hasClass() увеличена в 3 раза.
.toggleClass() может переключать несколько классов одновременно
Теперь вы можете вызвать метод .toggleClass() с несколькими именами классов, и все они будут переключаться.
1
$("div").toggleClass("current active");
Данные (Data)
.data() возвращает объект, а .data(Object) устанавливает объект
Иногда нужно работать с данными, прикрепленными к элементу в виде объекта. Часто необходимо скопировать все данные из одного элемента в другой. В jQuery 1.4 метод .data() без параметров возвращает весь объект целиком, а .data(Object) устанавливает объект. Имейте в виду, что объект включает события, прикрепленные к элементу, так что будьте осторожны при его использовании.
Кеш данных больше не создается, если он не нужен
jQuery uses a unique expando on DOM elements that is used to get the .data() for a particular element. jQuery now avoids creating that expando when data is looked up but no data has been added. This potentially increases performance and avoids polluting the DOM in these cases.
Эффекты (Effects)
Per-property Easing
Теперь вы можете указать функции управления анимацией (easing) для отдельных свойств элементов.
1
$("#clickme").click(function() {
2
$("div").animate({
3
width: ["+=200px", "swing"],
4
height: ["+=50px", "linear"],
5
}, 2000, function() {
6
$(this).after("<div>Анимация завершена.</div>");
7
});
8
});
События
Новый метод: jQuery.proxy()
Если вы хотите достичь того, чтобы “this” внутри функции был прочно связан с определённым значением, вы можете использовать jQuery.proxy, чтобы возвратить новую функцию с нужной областью видимости.
1
varobj = {
2
name: "John",
3
test: function() {
4
alert( this.name );
5
$("#test").unbind("click", obj.test);
6
}
7
};
8
$("#test").click( jQuery.proxy( obj, "test") );
Множественная привязка событий
Теперь вы можете передать методу .bind() объект, содержащий несколько событий.
01
$("div.test").bind({
02
click: function(){
03
$(this).addClass("active");
04
},
05
mouseenter: function(){
06
$(this).addClass("inside");
07
},
08
mouseleave: function(){
09
$(this).removeClass("inside");
10
}
11
});
События `change` и `submit` унифицированы
События change и submit надежно работают во всех браузерах для нормальных событий и событий реального времени. Мы перекрываем нормальные события change и submit в Internet Explorer и заменяем их событиями, которые работают так же, как и во всех остальных браузерах.
Новые события: `focusin` и `focusout`
Вообще события focusin и focusout являются эквивалентами focus и blur, but bubble, which helps tremendously if you are writing your own event delegation behavior. Пожалуйста, заметьте, что функции `focus` и `blur` не работают с методом live(); this was a design decision due to the DOM Events spec defining focus/blur do not bubble.
1
$("form").focusout(function(event) {
2
vartgt = event.target;
3
if(tgt.nodeName == "INPUT"&& !tgt.value) {
4
$(tgt).after("<span>nothing here</span>");
5
}
6
});
Манипуляция
Производительность увеличена
Несколько методов манипуляции с DOM стали значительно быстрее в jQuery 1.4. Увеличена производительность методов .append(), .prepend(), .before() и .after().
Производительность .html() улучшена приблизительно в 3 раза.
Скорость выполнения .remove() и .empty() увеличена в 4 раза.
Новый метод .detach()
Метод detach() удаляет элемент из DOM, но не удаляет связанные обработчики событий. Этот метод подходит для временного удаления элемента с последующим его восстановлением.
1
varfoo = $("#foo").click(function() {
2
// do something
3
});
4
foo.detach();
5
// foo retains event handlers
6
foo.appendTo("body");
Новый метод unwrap()
Метод unwrap() удаляет переданный ему элемент, оставляя его потомков без изменений. Подобно этому:
1
<body>
2
<div>
3
<p>annie</p> <p>davey</p> <p>stevie</p>
4
</div>
5
</body>
1
$('div').unwrap();
1
<body>
2
<p>annie</p> <p>davey</p> <p>stevie</p>
3
</body>
Кеширование в domManip
jQuery кэширует узлы, созданные с использованием таких методов, как jQuery("<div>") и .after("<div>"). Благодаря этому увеличивается производительность на страницах, на которых выполняются DOM-манипуляции со строками, использующих эти методы.
before, after, replaceWith с несвязанными узлами
Теперь вы можете применять before, after и replaceWith к узлам, которые не прикреплены к DOM. Это позволит вам делать более сложные манипуляции перед вставкой законченной структуры в дерево DOM.
В jQuery 1.3 метод .clone(true)не клонировал данные. В jQuery 1.4 он выполняет клонирование данных, что означает и возможность клонирования событий. Он использует ту же семантику, что и jQuery.extend, так что простые объекты и массивы будут клонироваться, а пользовательские объекты нет.
Смещение (Offset)
.offset( coords | Function )
Теперь можно установить смешение элемента, причем метод offset(), как и другие функции установки, может принимать функцию в качестве аргумента.
Организация очередей (Queueing)
Чтобы улучшить работу с очередями, мы полностью пересмотрели их организацию, отличную от стандатной fx.
Новый метод .delay()
Метод .delay() приводит к задержке всех дальнейших элементов в очереди на определённое количество миллисекунд. По умолчанию используется очередь эффектов fx. Вы можете указать альтернативную (другую) очередь в качестве второго аргумента функции delay.
1
$("div").fadeIn().delay(4000).fadeOut();
Queue next()
В jQuery 1.4 the function that’s called is passed in another function, as the first argument, that when called automatically dequeues the next item and keeps the queue moving.
1
jQuery("div").queue("ajax", function(next) {
2
varself = this;
3
jQuery.getJSON("/update", function(json) {
4
$(self).html(json.text);
5
next();
6
};
7
}).queue("ajax", function() {
8
$(this).fadeIn();
9
});
.clearQueue()
Теперь очередь можно очищать. Метод .clearQueue() удаляет все невыполненные функции из очереди, но не останавливает функции, выполняемые в данный момент. Использование .clearQueue() без параметров приведет к очистке fx очереди.
Селекторы (Selectors)
"#id p" стал быстрее. Любая строка селекторов, которая начинается с идентификатора работает более оптимизированно. Селекторы, начинающиеся с ID, всегда будут быстрее.
Обход (Traversing)
.index(), .index(String)
Метод .index() был переписан и стал более удобным.
Теперь вы можете получить индекс элемента по отношению к элементам того же уровня:
1
// получить индекс первого <li> по отношению к его "братьям":
2
$("li.current").index()
Вы можете получить индекс элемента по отношению к текущей коллекции jQuery, передав в качестве аргумента селектор или элемент DOM:
1
// получить индекс <h3 id="more-info"> по отношению ко всем элементам <h3>:
2
$("#more-info").index("h3")
Новый метод .has()
Этот метод аналогичен фильтру :has(). Он принимает набор jQuery и возвращает те элементы из этого набора, которые содержат указанный в параметре селектор.
Новые методы .nextUntil(), .prevUntil(), .parentsUntil()
Новые методы типа «until» похожи на .nextAll(), .prevAll(), .parents(), но в качестве аргумента принимают селектор, по достижении которого обход останавливается.
.add(String, Element)
Теперь метод .add() может использовать контекст. Эта функция особенно полезна, если вы хотите добавить дополнительные элементы (например, возвращенные ajax-запросом) и затем манипулировать ими вместе с остальными элементами.
.closest(filter, DOMElement)
Метод closest теперь может принимать в качестве второго аргумента контекст в виде DOMElement. Как правило, при использовании контекста метод closest() работает быстрее.
Утилиты (Utilities)
jQuery.isEmptyObject()
Эта функция возвращает true, если объект не содержит ни одного свойства. Теперь достаточно передать объект в jQuery.isEmptyObject(), и jQuery выполнит итерации по переданному объекту без каких-либо других проверок.
jQuery.isPlainObject()
jQuery.isPlainObject() возвратит true, если объект является литералом, и false, если объект другого типа.
jQuery.contains()
jQuery.contains() возвратит true, если оба аргумента узлы DOM и второй аргумент находится внутри первого.
jQuery.noop
jQuery.noop — пустая функция, которая может быть использована, если вам просто требуется функция для каких-либо целей.
jQuery.unique()
В jQuery 1.4 метод jQuery.unique(), используемый разработчиками внутри библиотеки для создания набора jQuery, удаляет дубликаты из набора и возвращает остальные элементы в том же порядке, что они были и на входе.
Прочее
jQuery.browser теперь может определять тип движка браузера
Например, вы можете проверить, является ли Webkit движком браузера с помощью функции jQuery.browser.webkit.
Улучшенная поддержка апплетов
jQuery больше не пытается присоединить события или данные к Java-апплетам (которые генерируют исключения).
Теперь для сжатия исходного кода библиотеки используется Closure Compiler вместо YUI Min
Внутренняя реорганизация кода
Одним из главных изменений в новой версии было создание более четкой и понятной кодовой базы.
Вот некоторые из изменений:
Старый файл ‘core.js’ был разделен на ‘attribute.js’, ‘css.js’, ‘data.js’, ‘manipulation.js’, ‘traversing.js’ и ‘queue.js’.
Событие ready было перемещено в core.js (так как это базовая часть jQuery).
Большая часть кода соответствует новым рекомендациям по оформлению кода jQuery.
Логика для работы с CSS и атрибутами была разделена и стала менее запутанной.
Тестирование
В jQuery 1.4 мы исправили 207 багов (по сравнению с 97 багами в релизе версии 1.3).
Кроме того мы увеличили количество тестов с 1504 в jQuery 1.3.2 до 3060 в jQuery 1.4.
Набор тестов jQuery был на 100% пройден всеми популярными браузерами (Safari 3.2, Safari 4, Firefox 2, Firefox 3, Firefox 3.5, IE 6, IE 7, IE 8, Opera 10.10 и Chrome).
Тест нашего журнала
Тест был проведен на компьютере с характеристиками: Intel Pentium IV 3ГГц, 2ГБ RAM, ОС Windows XP Professional SP 2.
Функция
jQuery 1.3.2
jQuery 1.4
Opera 10.10
class
addClass
125
15
addClassMulti
266
47
hasClass
609
63
removeClass
266
141
removeClassMulti
187
156
attr
css
188
125
cssMulti
593
485
attr
187
110
attrMulti
328
250
dom
appendLI
31
47
appendLIs
188
125
appendTR
31
31
appendTRs
78
32
appendToA
437
344
replaceContents
172
94
createElement
15
31
empty
empty
921
250
remove
4516
375
Итог
9138
2721
Mozilla Firefox 3.5.7
class
addClass
226
54
addClassMulti
364
42
hasClass
519
77
removeClass
349
100
removeClassMulti
280
103
attr
css
332
151
cssMulti
971
542
attr
241
175
attrMulti
436
265
dom
appendLI
157
100
appendLIs
367
267
appendTR
168
38
appendTRs
234
71
appendToA
743
539
replaceContents
539
185
createElement
40
34
empty
empty
1509
328
remove
7447
672
Итог
14922
3743
Internet Explorer 8
class
addClass
343
157
addClassMulti
563
188
hasClass
1375
313
removeClass
609
281
removeClassMulti
485
297
attr
css
359
250
cssMulti
1109
812
attr
625
390
attrMulti
1516
1094
dom
appendLI
187
140
appendLIs
282
188
appendTR
141
63
appendTRs
172
93
appendToA
1625
1329
replaceContents
672
203
createElement
47
31
empty
empty
3047
781
remove
13781
3562
Итог
26938
10172
Google Chrome 3
class
addClass
86
14
addClassMulti
178
26
hasClass
268
24
removeClass
152
65
removeClassMulti
97
43
attr
css
170
86
cssMulti
669
403
attr
120
88
attrMulti
328
173
dom
appendLI
48
36
appendLIs
81
75
appendTR
45
25
appendTRs
61
33
appendToA
262
256
replaceContents
200
87
createElement
12
12
empty
empty
646
207
remove
2583
344
Итог
6006
1997
Apple Safari 4
class
addClass
69
28
addClassMulti
94
33
hasClass
293
49
removeClass
111
56
removeClassMulti
86
52
attr
css
176
99
cssMulti
565
361
attr
125
86
attrMulti
231
154
dom
appendLI
39
35
appendLIs
61
64
appendTR
27
32
appendTRs
39
34
appendToA
242
257
replaceContents
153
82
createElement
10
9
empty
empty
640
239
remove
2811
356
Итог
5772
2026
Таким образом по производительности лидирует Chrome 3, незначительно опережая Safari 4. Браузеры Opera и Firefox догоняют их с отставанием в скорости на 136% и 187% соответственно. Как и можно было ожидать в конце плетётся IE8, показав 5-кратное отставание в производительности от лидеров. Причем сей убогий браузер в ходе тестирования на двух последних тестах несколько раз зависал.