От переводчика: Не смотря на то что оригинал данной статьи датирован январем 2009 года, она не потеряла актуальности и теперь. Я надеюсь что даже те, кто используют JavaScript не первый год, почерпнут для себя что-то полезное.
В JavaScript существует два разных типа операций сравния: === / !== и == / !=. Считается хорошим тоном всегда использовать первую пару для сравнения.
Для тех кто не знаком, функция «eval» дает нам доступ к компилятору JavaScript. Т.е. мы можем выполнить команду записанную в строковой переменной, которую передадим в качестве параметра в eval.
Это не только замедлит вашу программу, но еще и предполагает возниковение огромной дыры безопасности вашего приложения. Это плохо. По возможности избегайте этого.
Технически можно писать код без фигурных скобок и точек с запятой. Большинство браузеров корректно воспримет следующий код:
Как насчет этого?
Кто-то может посчитать что это эквивалентно следующему
И он будет неправ. Потому что на самом деле для компилятора это выглядит так:
Как вы заметили отступ маскирует функционал фигурных скобок. Излишне говорить, что это ужасная практика, которую следует избегать любой ценой. Единственное где вы можете опустить использование скобок это в однострочных выражениях, но даже это вызывает кучу споров. (Я против даже такого. Прим. пер.)
JSLint это анализатор кода (в оригинале debugger, но это не так — прим. пер.), написанный Дугласом Крокфордом. Просто вставьте в него свой код и он быстро проанализирует на предмет возможных проблем и ошибок.
Прежде чем закоммитить код, прогоните его через JSLint чтобы проверить на наличие ошибок, которые вы могли проглядеть.
Между прочим IDE от JetBrains такие как WebStorm/PyCharm/PHPStorm имеют встроенный анализ JSLint.
Таким образом следить за чистотой кода стало еще проще. Прим. пер.
Основная цель этого совета — заставить страницу грузиться как можно быстрее. Когда браузер грузит скрипт он не продолжит рендеринг пока весь файл не будет загружен. Таким образом пользователю придется ждать дольше.
Если ваши JS скрипты служать для добавления функционала — например, обработки кликов кнопки то вам стоит перенести скрипты вниз поставив их перед закрывающимся тегом body.
Когда выполняете долгий цикл «for» не заставляйте делать движок больше работы чем нужно.
Обратите внимание как мы должны высчитываем длинну массива для каждой итерации и как мы обходим дерево для поиска #container.
Тот кто напишет в комментариях как еще можно улучшить этот блок кода пусть возьмет с полки пирожок.
For это не всегда лучший способ для того чтобы обойти массив или объект. Будьте изобретательны и вы найдете наиболее быстрое решение для текущей задачи.
Мы уменьшили количество глобальных переменных до одного, странным образом названного, обьекта «DudeNameSpace».
Это кажется излишним в начале, но поверьте мне вы действительно ХОТИТЕ комменировать ваш код как можно лучше. Что случится когда вы вернетесь к проекту через несколько месяце чтобы обнаружить что не помните что этот кусок кода делаете. Или что будет если ваш коллега будет смотреть ваш код в процессе код-ревью? Всегда, повторяю всегда комментируйте важные части кода.
Всегда принимайте во внимание выключенный JavaScript. Очень соблазнительно думать «Большая часть моих пользователей не отключает JS, так что зачем мне беспокоиться». Тем не менее это большая ошибка.
А не пробовали ли вы на момент взглянуть на ваш красивый слайдер с отлюченным Javascript? (Скачайте the Web Developer Toolbar чтобы быстро проверить это.) Он может сломать полностью весь ваш сайт. Проектируйте дизайн сайта предполагая что JS может быть отключен. И уже после этого начинайте улучшать макет используя JavaScript.
Если вы не знакомы с термином «прогрессивное улучшение» то рекомендую обратить внимание на хабрастатью Progressive Enhancement или всё-таки Graceful Degradation. Прим. пер.
Рассмотрим следующий код:
Он не только неэффективен, но еще и работает так же как и «eval». Результаты будут такие-же. Вместо этого передавайте функцию в качестве аргумента.
На первый взгляд оператор with выглядит как неплохая идея. Концепция его в предоставлении более короткого доступа к глубоко вложенным обьектам. Например используя
вместо
К сожалению, после некоторого тестирования обнаруживается что установка новых членов ведет себя плохо. Вместо этого используйте такой вариант:
Есть несколько путей для создания объектов в JavaScript. Возможно наиболее традиционный это использование конструктора «new», например
Хотя этот метод получил штамп «плохой практики» он таковой не является. Вместо него, я рекомендую использовать более надежный метод c литералом обьекта
Заметка — если вы хотите создать пустой обьект, то {} сделает это
Правило выше годится и для массивов.
Этот код должен говорить сам за себя. Я сомневаюсь что тут есть какие-то подвижки в скорости, но код выглядит чище.
Технически, большинство браузеров позволят вам не использовать их.
Но использование подобную практики потенциально может привести к гораздо более большим и что еще хуже плохо отлавливаемым проблемам.
Примечание переводчика:
Как правильно указал в комментариях armed в некоторых случаях точка с запятой будет установлена автоматически, причем не так как вы думаете.
Цитата из перевода спецификации ECMA (eng):
При проходе в цикле через свойстав обьекта вы также обнаружите что получаете в том числе и функции. Для избежания этого необходима проверка с if hasOwnProperty
Из „JavaScript: The Good Parts“ Douglas Crockford.
Вообще Object.prototype.hasOwnProperty проверяет принадлежит ли свойство непосредственно обьекту а не его цепочке прототипов. Подробнее можно почитать в JavaScript Garden
У Ильи Кантора встречается более элегантная форма записи
но честно говоря я не уверен какие браузеры могут корректно обрабатывать ее.
Прим. пер.
Нужен быстрый и легкий способ чтобы определить как много времени займет операция? Используйте консольный таймер для логирования результатов.
В то время как я большой фанат блогов по разработке (например этого), это все-таки не заменитель книги для чтения во время обеда или перед сном. Всегда держите книгу по разработке на прикроватной тумбочке. Вот несколько моих любимых по JavaScript-у.
Object-Oriented JavaScript
JavaScript: The Good Parts
Learning jQuery 1.3
Learning JavaScript
Читайте и перечитывайте. Как я!
Вместо вызова функции где-то еще это довольно просто заставить функцию вызывать себя автоматически на загрузке страницы. Просто оберните функцию в скобки и добавьте еще одни после для непосредственного вывода.
(function doSomething() {
return {
name: 'jeff',
lastName: 'way'
};
})();
Это называется Immediately-Invoked Function Expression. И чаще используется для создания приватной области видимости. Подробнее на JavaScript Garden. Прим. пер.
Не мог не удержаться. Прим. пер.
JavaScript-библиотеки, такие как jQuery и Mootools экономят невероятное количество времени при разработке — особенно при работе с AJAX. Но так же не забывайте что библиотеки никогда не будут такими быстрыми как чистый JavaScript (в случае корректного кода)
Метод jQuery „each“ отлично подходит для циклов, но использование нативного оператора „for“ всегда будет быстрее.
Несмотря на то что JavaScript 2 должен иметь встроенный парсер JSON, на момент публикации (январь 2009), нам все еще следует включать стороннюю реализацию. Douglas Crockford, создатель JSON, уже создал парсер, который вы можете испольозовать. Его можно загрузить здесь.
После загрузки скрипта у Вас будет доступ к глобальному обьекту JSON, который может быть использован для парсинга соответствующих файлов.
C момента публикации статьи прошло 4 года, и вы должны подключать стороннюю библиотеку только для IE7 и некоторых мобильных браузеров. caniuse.com/#search=JSON.parse
Второй момент это то, что при использовании jQuery ответы в json автоматически парсятся в обьекты при условии что сервер отдает application-type: „application/json“ или „text/javascript“, а так-же если вы напрямую указали тип ответа в $.get, $.post или $.ajax. При. пер.
Давным-давно это не было редкой практикой использования аттрибута language у тега script.
Сейчас же он считается устаревшим. Избавьтесь от него.
Послесловие переводчика:
Для тех кто действительно хочет в совершенстве овладеть JavaScript-ом рекомендую изучить следующие ресурсы:
Javascript Garden — english, перевод на русский
Современный учебник на javascript.ru — http://learn.javascript.ru/
Я и остальные читатели хабра будут очень рады, если вы добавите свои советы. Наиболее полезные я буду выносить в топик. Спасибо.
1. Используйте === вместо ==
В JavaScript существует два разных типа операций сравния: === / !== и == / !=. Считается хорошим тоном всегда использовать первую пару для сравнения.
“Если два операнда одного типа и значения, то === вернет true, а !== false”
JavaScript: The Good Parts
2. Eval = зло
Для тех кто не знаком, функция «eval» дает нам доступ к компилятору JavaScript. Т.е. мы можем выполнить команду записанную в строковой переменной, которую передадим в качестве параметра в eval.
Это не только замедлит вашу программу, но еще и предполагает возниковение огромной дыры безопасности вашего приложения. Это плохо. По возможности избегайте этого.
3. Не используйте короткую запись
Технически можно писать код без фигурных скобок и точек с запятой. Большинство браузеров корректно воспримет следующий код:
if(someVariableExists)
x = false
Как насчет этого?
if(someVariableExists)
x = false
anotherFunctionCall();
Кто-то может посчитать что это эквивалентно следующему
if(someVariableExists) {
x = false;
anotherFunctionCall();
}
И он будет неправ. Потому что на самом деле для компилятора это выглядит так:
if(someVariableExists) {
x = false;
}
anotherFunctionCall();
Как вы заметили отступ маскирует функционал фигурных скобок. Излишне говорить, что это ужасная практика, которую следует избегать любой ценой. Единственное где вы можете опустить использование скобок это в однострочных выражениях, но даже это вызывает кучу споров. (Я против даже такого. Прим. пер.)
if(2 + 2 === 4) return 'nicely done';
4. Используйте JS Lint
JSLint это анализатор кода (в оригинале debugger, но это не так — прим. пер.), написанный Дугласом Крокфордом. Просто вставьте в него свой код и он быстро проанализирует на предмет возможных проблем и ошибок.
JSLint сканирует JavaScript код. Если он находит проблему, то возвращает сообщение с описанием и местонахождение в коде. Проблема это не обязательно ошибка синтаксиса, хотя часто так и есть. JSLint так-же обращает внимание на соглашения о кодировании а так же на проблемы в структуре. Он не доказывает что ваша программа работает верно.Он просто предоставляет еще один взгляд на ваш код.”
– JSLint Documentation
Прежде чем закоммитить код, прогоните его через JSLint чтобы проверить на наличие ошибок, которые вы могли проглядеть.
Между прочим IDE от JetBrains такие как WebStorm/PyCharm/PHPStorm имеют встроенный анализ JSLint.
Таким образом следить за чистотой кода стало еще проще. Прим. пер.
5. Переместите скрипты вниз страницы
Основная цель этого совета — заставить страницу грузиться как можно быстрее. Когда браузер грузит скрипт он не продолжит рендеринг пока весь файл не будет загружен. Таким образом пользователю придется ждать дольше.
Если ваши JS скрипты служать для добавления функционала — например, обработки кликов кнопки то вам стоит перенести скрипты вниз поставив их перед закрывающимся тегом body.
<p>And now you know my favorite kinds of corn. </p>
<script type="text/javascript" src="path/to/file.js"></script>
<script type="text/javascript" src="path/to/anotherFile.js"></script>
</body>
</html>
6. Объявляйте переменные для 'for" вне циклов
Когда выполняете долгий цикл «for» не заставляйте делать движок больше работы чем нужно.
Плохо
for(var i = 0; i < someArray.length; i++) {
var container = document.getElementById('container');
container.innerHtml += 'my number: ' + i;
console.log(i);
}
Обратите внимание как мы должны высчитываем длинну массива для каждой итерации и как мы обходим дерево для поиска #container.
Лучше
var container = document.getElementById('container');
for(var i = 0, len = someArray.length; i < len; i++) {
container.innerHtml += 'my number: ' + i;
console.log(i);
}
Тот кто напишет в комментариях как еще можно улучшить этот блок кода пусть возьмет с полки пирожок.
7. Самый быстрый способ получить строку
For это не всегда лучший способ для того чтобы обойти массив или объект. Будьте изобретательны и вы найдете наиболее быстрое решение для текущей задачи.
var arr = ['item 1', 'item 2', 'item 3', ...];
var list = '<ul><li>' + arr.join('</li><li>') + '</li></ul>';
Я не собираюсь давать вам скучные бенчмарки, но поверьте мне (или проверьте сами) это действительно самый быстрый способ.
Использование нативных методов (таких как join()), независимо от того что происходит за слоем абстракции гораздо быстрее чем любая ненативная альтернатива.
— James Padolsey, james.padolsey.com
8. Уменьшите количество глобальных переменных
«Сведением количества глобальных переменных к одному, вы значительно снижаете шансы нежелательного взаимодействия с другими приложениями, виджетами или библиотеками.»
— Douglas Crockford
var name = 'Jeffrey';
var lastName = 'Way';
function doSomething() {...}
console.log(name); // Jeffrey -- or window.name
Лучше
var DudeNameSpace = {
name : 'Jeffrey',
lastName : 'Way',
doSomething : function() {...}
}
console.log(DudeNameSpace.name); // Jeffrey
Мы уменьшили количество глобальных переменных до одного, странным образом названного, обьекта «DudeNameSpace».
9. Комментируйте ваш код
Это кажется излишним в начале, но поверьте мне вы действительно ХОТИТЕ комменировать ваш код как можно лучше. Что случится когда вы вернетесь к проекту через несколько месяце чтобы обнаружить что не помните что этот кусок кода делаете. Или что будет если ваш коллега будет смотреть ваш код в процессе код-ревью? Всегда, повторяю всегда комментируйте важные части кода.
// Cycle through array and echo out each name.
for(var i = 0, len = array.length; i < len; i++) {
console.log(array[i]);
}
10. Воспользуйтесь прогрессивным улучшением (progressive enchantment)
Всегда принимайте во внимание выключенный JavaScript. Очень соблазнительно думать «Большая часть моих пользователей не отключает JS, так что зачем мне беспокоиться». Тем не менее это большая ошибка.
А не пробовали ли вы на момент взглянуть на ваш красивый слайдер с отлюченным Javascript? (Скачайте the Web Developer Toolbar чтобы быстро проверить это.) Он может сломать полностью весь ваш сайт. Проектируйте дизайн сайта предполагая что JS может быть отключен. И уже после этого начинайте улучшать макет используя JavaScript.
Если вы не знакомы с термином «прогрессивное улучшение» то рекомендую обратить внимание на хабрастатью Progressive Enhancement или всё-таки Graceful Degradation. Прим. пер.
11. Не передавайте строку в «SetInterval» или «SetTimeOut»
Рассмотрим следующий код:
setInterval(
"document.getElementById('container').innerHTML += 'My new number: ' + i", 3000
);
Он не только неэффективен, но еще и работает так же как и «eval». Результаты будут такие-же. Вместо этого передавайте функцию в качестве аргумента.
setInterval(someFunction, 3000);
12. Не используйте оператор with
На первый взгляд оператор with выглядит как неплохая идея. Концепция его в предоставлении более короткого доступа к глубоко вложенным обьектам. Например используя
with (being.person.man.bodyparts) {
arms = true;
legs = true;
}
вместо
being.person.man.bodyparts.arms = true;
being.person.man.bodyparts.legs= true;
К сожалению, после некоторого тестирования обнаруживается что установка новых членов ведет себя плохо. Вместо этого используйте такой вариант:
var o = being.person.man.bodyparts;
o.arms = true;
o.legs = true;
13. Используйте {} вместо New Object()
Есть несколько путей для создания объектов в JavaScript. Возможно наиболее традиционный это использование конструктора «new», например
var o = new Object();
o.name = 'Jeffrey';
o.lastName = 'Way';
o.someFunction = function() {
console.log(this.name);
}
Хотя этот метод получил штамп «плохой практики» он таковой не является. Вместо него, я рекомендую использовать более надежный метод c литералом обьекта
Лучше
var o = {
name: 'Jeffrey',
lastName = 'Way',
someFunction : function() {
console.log(this.name);
}
};
Заметка — если вы хотите создать пустой обьект, то {} сделает это
var o = {};
Литералы обьектов позволят нам писат код, который поддерживает кучу функционала все еще сохраняя относительную непосредственность. Не нужно больше вызывать конструкторы напрямую или корректировать порядок аргументов переданных в функцию.
— dyn-web.com, http://ww.dyn-web.com/tutorials/obj_lit.php
14. Используйте [] вместо new Array()
Правило выше годится и для массивов.
Нормально
var a = new Array();
a[0] = "Joe";
a[1] = 'Plumber';
Лучше
var a = ['Joe','Plumber'];
«Распространенная ошибка в JavaSсript программах — использование объекта, где нужен массив или массива где нужен обьект. Простое правило: когда названия свойств это небольшие последовательные числа — используйте массив. В противном случае — объект.
Douglas Crockford
15. Длинный список переменных? Опустите „var“ и используйте запятые
var someItem = 'some string';
var anotherItem = 'another string';
var oneMoreItem = 'one more string';
Лучше
var someItem = 'some string',
anotherItem = 'another string',
oneMoreItem = 'one more string';
Этот код должен говорить сам за себя. Я сомневаюсь что тут есть какие-то подвижки в скорости, но код выглядит чище.
17. Всегда, всегда используйте точку с запятой
Технически, большинство браузеров позволят вам не использовать их.
var someItem = 'some string'
function doSomething() {
return 'something'
}
Но использование подобную практики потенциально может привести к гораздо более большим и что еще хуже плохо отлавливаемым проблемам.
Лучше
var someItem = 'some string';
function doSomething() {
return 'something';
}
Примечание переводчика:
Как правильно указал в комментариях armed в некоторых случаях точка с запятой будет установлена автоматически, причем не так как вы думаете.
Цитата из перевода спецификации ECMA (eng):
Некоторые инструкции ECMAScript (пустая инструкция, объявление переменной, инструкция-выражение, инструкция do-while, инструкция continue, инструкция break, инструкция return, и инструкция throw) должны оканчиваться точками с запятыми. Эти точки с запятыми могут явно указываться в тексте. Однако в некоторых случаях, исходя из соображений удобства, такие точки с запятыми в исходном тексте могут быть опущены. Эти ситуации описываются высказыванием, гласящим, что точки с запятой автоматически вставляются в поток токенов исходного текста в этих ситуациях.
18. Оператор „for… in“
При проходе в цикле через свойстав обьекта вы также обнаружите что получаете в том числе и функции. Для избежания этого необходима проверка с if hasOwnProperty
for(key in object) {
if(object.hasOwnProperty(key)) {
...then do something...
}
}
Из „JavaScript: The Good Parts“ Douglas Crockford.
Вообще Object.prototype.hasOwnProperty проверяет принадлежит ли свойство непосредственно обьекту а не его цепочке прототипов. Подробнее можно почитать в JavaScript Garden
У Ильи Кантора встречается более элегантная форма записи
for(prop in object) if (object.hasOwnProperty(prop)) {
//...
}
но честно говоря я не уверен какие браузеры могут корректно обрабатывать ее.
Прим. пер.
19. Используйте таймер консоли для оптимизации кода
Нужен быстрый и легкий способ чтобы определить как много времени займет операция? Используйте консольный таймер для логирования результатов.
function TimeTracker(){
console.time("MyTimer");
for(x=5000; x > 0; x--){}
console.timeEnd("MyTimer");
}
20. Читайте, читайте, читайте...
В то время как я большой фанат блогов по разработке (например этого), это все-таки не заменитель книги для чтения во время обеда или перед сном. Всегда держите книгу по разработке на прикроватной тумбочке. Вот несколько моих любимых по JavaScript-у.
Object-Oriented JavaScript
JavaScript: The Good Parts
Learning jQuery 1.3
Learning JavaScript
Читайте и перечитывайте. Как я!
21. Self-Executing Functions
Вместо вызова функции где-то еще это довольно просто заставить функцию вызывать себя автоматически на загрузке страницы. Просто оберните функцию в скобки и добавьте еще одни после для непосредственного вывода.
(function doSomething() {
return {
name: 'jeff',
lastName: 'way'
};
})();
Это называется Immediately-Invoked Function Expression. И чаще используется для создания приватной области видимости. Подробнее на JavaScript Garden. Прим. пер.
22. Чистый JavaScript может быть быстрее чем использование библиотек
— Вы готовы дети?
— Да, Капитан!
— Я не слыыышуууу!
—ТАК ТОЧНО, КАПИТАН!
— из заставки к Sponge Bob Square Pants
Не мог не удержаться. Прим. пер.
JavaScript-библиотеки, такие как jQuery и Mootools экономят невероятное количество времени при разработке — особенно при работе с AJAX. Но так же не забывайте что библиотеки никогда не будут такими быстрыми как чистый JavaScript (в случае корректного кода)
Метод jQuery „each“ отлично подходит для циклов, но использование нативного оператора „for“ всегда будет быстрее.
23. JSON.Parse Крокфорда
Несмотря на то что JavaScript 2 должен иметь встроенный парсер JSON, на момент публикации (январь 2009), нам все еще следует включать стороннюю реализацию. Douglas Crockford, создатель JSON, уже создал парсер, который вы можете испольозовать. Его можно загрузить здесь.
После загрузки скрипта у Вас будет доступ к глобальному обьекту JSON, который может быть использован для парсинга соответствующих файлов.
var response = JSON.parse(xhr.responseText);
var container = document.getElementById('container');
for(var i = 0, len = response.length; i < len; i++) {
container.innerHTML += '<li>' + response[i].name + ' : ' + response[i].email + '</li>';
}
C момента публикации статьи прошло 4 года, и вы должны подключать стороннюю библиотеку только для IE7 и некоторых мобильных браузеров. caniuse.com/#search=JSON.parse
Второй момент это то, что при использовании jQuery ответы в json автоматически парсятся в обьекты при условии что сервер отдает application-type: „application/json“ или „text/javascript“, а так-же если вы напрямую указали тип ответа в $.get, $.post или $.ajax. При. пер.
24. Уберите „language“
Давным-давно это не было редкой практикой использования аттрибута language у тега script.
<script type="text/javascript" language="javascript">
...
</script>
Сейчас же он считается устаревшим. Избавьтесь от него.
Послесловие переводчика:
Для тех кто действительно хочет в совершенстве овладеть JavaScript-ом рекомендую изучить следующие ресурсы:
Javascript Garden — english, перевод на русский
Современный учебник на javascript.ru — http://learn.javascript.ru/
Я и остальные читатели хабра будут очень рады, если вы добавите свои советы. Наиболее полезные я буду выносить в топик. Спасибо.