понедельник, 17 марта 2008 г.

Оптимизация JavaScript (String IE)

В этот раз оптимизация касается «любимого» всеми браузера IE. По какой-то причине конкатенация строк в ослике тотально медленная, поэтому приходится мудрить.
Кто сталкивался с динамическим обновлением контента (ajax), эта функция в той или иной конфигурации очень знакома.



function createList(){
var el = document.getElementById('list');
var html = '<ul>';
for (var i = 1; i <= 1000; i++) {
html += '<li>Element';
html += i;
html += '</li>';
}
html += '</ul>';
el.innerHTML = html;

}

Итак посмотрим на время выполнения скрипта.

Mozilla: 31ms;
Opera: 16ms (как всегда радует);
IE6: 230ms (никуда не годится…);
IE7: 67ms (немного лучше);

Выход из этой ситуации есть, он довольно прост и неожидан.

function createList(){
var html = [];
html.push('<ul>');
for (var i = 1; i <= 1000; i++) {
html.push('<li>Element');
html.push(i);
html.push('</li>');
}
html.push('<ul>');
var el = document.getElementById('list');
el.innerHTML = html.join('');
}


Mozilla: 47ms (тут пришлось немного пожертвовать скоростью);
Opera: 16ms ;
IE6: 31ms (другое дело);
IE7: 32ms (и тут получше);

Как, я уже писал никогда не пишите … el.innerHTML += '<li>' … даже если операций совсем немного, присваивайте к innerHTML уже готовый результат.

суббота, 2 февраля 2008 г.

Оптимизируем работу с DOM

Работа с DOM элементами занимает слишком много времени, поэтому обращаться к свойствам следует как можно меньше.
Простой пример создания информационного блока, используя innerHTML:




function createHTML(block){
block.innerHTML = '';
block.innerHTML += createTitle();
block.innerHTML += createBody();
}

Не стоит оброщатся к элементу несколько раз, если можно обойтись одним:

function createHTML(block){
var temp = '';
temp += createTitle();
temp += createBody();
block.innerHTML = temp;
}

Кстати говоря, тоже самое относится и к document.write:

//Никогда так не делайте
document.write('текст');
document.write(txt);
document.write('текст');
//Пишите так:
var str = '';
str = 'текст'+txt+'текст';
document.write(str);

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

воскресенье, 27 января 2008 г.

Оптимизация JavaScript (addEvent)

Всем известная функция addEvent и ее стандартная реализация:


function addEvent(obj,name,func){
if(obj.addEventListener) {
obj.addEventListener(name, func, false);
}
else if (obj.attachEvent) {
obj.attachEvent('on'+name, func);
}
else {throw 'Error'};
}

Чтобы избежать постоянной проверки, следует проверять наличие нужных методов непосредственно при создании функции:
 
var addEvent= (function(){
if(document.addEventListener) {
return function(obj,name,func){
obj.addEventListener(name, func, false);
}
}
else if (document.attachEvent) {
return function(obj,name,func){
obj.attachEvent('on'+name, func);
}
}else return function(){throw 'Error'}
})()

Тот же способ можно применить и к detachEvent, removeEventListener.



пятница, 25 января 2008 г.

Оптимизация JavaScript (Array)

Добавление и извлечение последнего элемента массива.

Обычный способ:

var arr = new Array();
arr.push('a');
arr.pop();
//Быстрый способ:
var arr = [];
arr[arr.length]='a';
delete arr[arr.length-1]; // а вот так делать стоит,
ибо тогда arr.length == 1 и arr[0] = 'undefined' используйте arr.pop();
Спасибо Сергею, указал на ошибку :)





четверг, 24 января 2008 г.

Оптимизация JavaScript (Looping)

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


Обычная выборка из массива:

var a = [1,2,3,4,...]
for(var i=0;i<a.length;i++){
...
}
//Повысить скорость можно так:
var a = [1,2,3,4,...]
for(var i=0,l = a.length;i<l;i++){
...
}


Иногда можно просто изменить конструкцию, например функция in_array:

for(var i=0;i<arr.length;i++){
if(arr[i] === search)return true;
}return false;
//неплохой прирост скорости:
var i = arr.length;
while(i--){
if(arr[i] === search)return true;
}
return false;

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

В данном примере вызывается метод вложенного объекта:

for(var i=0;i<100;i++){
a.b.c.d(i);
}
//Сработает гораздо быстрее, если присвоит ссылку метода к переменной.
var d = a.b.c.d;
for(var i=0;i<100;i++){
d(i);
}

Более наглядный пример с формой:

var form = document.forms[0]
for(var i=0;i<form.radio.length;i++){
if(form.radio[i].checked)return form.radio[i].value;
}
//так шустрее:
var form = document.forms[0];
var radio = form.radio;
var l = radio.length;
for(var i=0;i<l;i++){
if(radio[i].checked)return radio[i].value;
}