Сайт Игоря Кононученко   Статьи

Анализируя JavaScript код

24 ноября 2008

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

Спрятать и показать

Типичный код, — абсолютно симметричная пара методов для сокрытия и показа чего-то. Но решение не самое лучшее из-за дублирования:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
show:function()
{
    this.container.style.visibility = "visible";
    this.open_button.style.visibility = "hidden";
},

hide:function()   
{
    this.container.style.visibility = "hidden";
    this.open_button.style.visibility = "visible";
},

Рефакторим:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
show:function()
{
   this.setState(true);
},

hide:function()   
{
    this.setState(false);        
},

_setState:function(showContainer)
{
    var visibility= ["visible","hidden"]; 
    this.container.style.visibility = visibility[showContainer?1:0];
    this.open_button.style.visibility = "visibility[showContainer?0:1];
}

Вполне резонно заметить, что получившегося кода стало больше на один метод и не ясно, стоит ли увеличивать комплексность кода. В данном случае экономия весьма не очевидна, как и затраты. Я за то чтобы делать рефакторинг, начиная с самого незначительного — все дело в стиле мышления (не говоря о гибкости, которая появилась). Поддерживая порядок, будешь жить в чистоте. Иначе — известно в чем.

Массивы

Часто можно встретить такой вид создания:

1
var arr = new Array();

Более короткая версия:

1
var arr = [];

Удаление элемента из массива. Интуитивно-понятного метода remove у массива нет, к сожалению. Поэтому можно встретить код:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function removeFromArray(arr, elem)
 {
     result = [];
     for(var i=0;i<arr.length;i++)
     {
         if(arr[i]==elem) continue;
         result.push(arr[i]);         
     }
     return result;
 }
Тут происходит простое копирование всего в новый массив, за исключением ненужного элемента. Не самый быстрый способ, особенно в случае большого массива. Пользователи библиотеки Prototype.js для этой часто используют метод — arr.without(el), который работает по той же самой схеме (все же замечу, что у прототайпа великолепные методы для расширения класса Array). Тривиально, но многие не знают, что удаление из массива выполняет встроенная операция — arr.splice(номер элемента, количество удаляемых элементов) — еще метод позволяет делать замену.

Создание элементов

Часто можно увидеть большое количество кода создающего DOM-структуру. Пишутся обертки для удобного создания DOM-елементов. А ведь решение — не самое производительное.

По производительности innerHTML — лучший. Исходя из этого, в большинстве случаев методы DOM отбрасываем (есть исключения, такие как тег — table в IE, он не дает ничего записать в свой innerHTML). Мне очень нравится класс Template в библиотеке Prototype, позволяющий создавать штмл подобным образом:

1
2
3
4
5
6
7
8
var template = new Template('<option value="#{id}">#{name}</option>');
var options = []
for(var i=0;i<cities.length;i++)
{
    var city = cities[i];
    options.push(template.evaluate(city));
}
this.cbCity.innerHTML = options.join("");
Для остальных пользователей легко придумать решение используя стандартный replace. Еще на один момент следует обратить внимание. Временным контейнером штмл является массив строк и в конце происходит this.cbCity.innerHTML = options.join(""); — это дает лучшую производительность.

В заключение

Мне еще попадались различные стандартные ситуации. По мере возможности, в будущем соберу их еще в одну часть.

Симметрия кода
Значение поля формы в Django-шаблоне
Ctrl
Алгоритм эффективного выполнения любого задания
Bind-функция для jQuery