Скрытые возможности JavaScript, которые должен знать каждый программист

Объявление параметров функции не является обязательным

В JavaScript Вы не обязаны объявлять параметры функции, если хотите что-то туда передать. Получить аргументы, переданные в функцию, можно с помощью массивоподобного объекта «arguments»:

function sum() {
var retval = 0;
for (var i = 0, len = arguments.length; i < len; ++i) {
retval += arguments[i];
}
return retval;
}
sum(1, 2, 3) // Вернёт 6

Заметьте, что я написал «массивоподобного объекта», а не «массива». Вы не можете работать с этим объектом как с массивом, ведь это на самом деле не массив: над ним нельзя выполнить join(), pop(), push(), slice() и тому подобное. Однако, Вы можете преобразовать его в реальный массив при необходимости:

var argArray = Array.prototype.slice.call(arguments);

Не лишним будет отметить, что использование этого объекта может работать несколько медленнее, чем обычная передача параметров в функцию.

Поосторожней со сравнением

Рекомендую Вам всегда использовать «===» и «!==» вместо «==» и «!=». Почему? Взгляните на это:

alert('''' == ''0''); //false
alert(0 == ''''); // true
alert(0 == ''0''); // true
alert(''\n\t\r '' == 0) // true

Не очень ожидаемые результаты, правда? А при использовании «===» все выражения вернули бы false.
Ещё пример:

var a = "строка";
var b = new String(a);
var c = new String(a);
alert(a==b); // true
alert(a==c); // true
alert(b==c); // false

Такое происходит потому, что оператор «==» не является транзитивным. В переводе с математического это означает, что если a==b и a==c, то это ещё не значит, что b==c. Поэтому очень важно понимать, что Вы сравниваете. 2 переменные считаются неравными, если они ссылаются на разные объекты (в случае выше b и c это 2 разные объекта типа String). А если сравниваются не объекты, а примитивные значения, то они переводятся в строки, а затем происходит сравнение.

Функции — это объекты

Функции в JavaScript тоже являются объектами:

var passFunAndApply = function (fn,x,y,z)
{
return fn(x,y,z);
};
var sum = function(x,y,z) {
return x+y+z;
};
alert(passFunAndApply(sum,3,4,5)); // 12

Как видите, здесь одна функция передаётся внутрь другой, в других языках программирования подобное обычно недопустимо.
Также можно объявить «приватную» функцию внутри другой:

function PrintName() {
var privateFunction = function() { return "Steve"; };
return privateFunction();
}

А ещё — функциям можно назначить собственные свойства.

fn = function(x) {
// ...
}
fn.foo = 1;
fn.next = function(y) {
//
}

Оператор in

Вы можете использовать оператор in, чтобы проверить, присутствует ли ключ в некотором объекте:

var x = 1;
var y = 3;
var list = {0:0, 1:0, 2:0};
x in list; //true
y in list; //false
1 in list; //true
y in {3:0, 4:0, 5:0}; //true

Область видимости в JavaScript

В JavaScript нет возможности ограничить область видимости, как это можно делать, например, в C:

var x = 1;
{
var x = 2;
}
alert(x); // Выведет 2

Впрочем, всегда можно сделать так:

var tmp = function() {
// Ограниченная область видимости
}();

Назначение значений по-умолчанию переменным

Вы можете использовать логический оператор «или» («||») в выражениях присвоения.

var a = b || c;

Переменная «a» получит значение «c» только в том случае, если «b» будет иметь нулевое значение (null, false, undefined, 0, пустая строка или NaN), иначе «a» получит значение «b» (так как «b» идёт первой).

Такой подход может быть очень полезен в функциях, в которых Вы хотите задать значение по-умолчанию:

function example(arg1) {
arg1 || (arg1 = ''значение по умолчанию'');
}

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

function onClick(e) {
e || (e = window.event);
}

Выражение «debugger»

Это выражение не являлось частью спецификации ECMAScript вплоть до 5й версии, но на практике все реализации JavaScript поддерживали его.

// ...
debugger;
// ...

Оно позволяет программно создать точку остановки. Остановка делается только в том случае, если дебаггер (аля FireBug) установлен и активный, в противном случае выражение игнорируется.

«Многострочные» строки

Одну строку можно разбить на несколько для удобного форматирования кода:

var str = "This is a \
really, really \
long line!";

Будьте осторожны, потому что символ, который следует за «\», должен быть обрывом строки (грубо говоря, там не должно быть ничего). Если туда добавить, например, пробел, код будет выглядеть также, но возникнет синтаксическая ошибка.

Доступ к свойству объекта через []

Вы можете получить доступ к свойствам объекта через [] вместо знака «.»
Это даст Вам возможность при получении свойства использовать не его имя, а переменную, которая содержит это имя:

obj = {a:"test"};
var propname = "a";
var b = obj[propname];  // "test"

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

obj["class"] = "test";  // class - это зарезервированное имя; obj.class вызвало бы ошибку.
obj["two words"] = "test2"; // использование точки недопустимо вместе с пробелом.

Я встречал, как некоторые люди, не зная этого, используют eval():

var propname = "a";
var a = eval("obj." + propname);

Это сложно читать, сложно тестировать, и к тому же работает медленнее.

Выводите переменные через console.log(varName)

Этот пункт присутствует здесь «на всякий случай». Некоторые начинающие программисты, по-незнанию, делают так:

alert(varName);

В современных браузерах есть средства отладки, которые позволяют использовать вывод переменных в консоль в удобном виде. Для Firefox можно установить Firebug — это, можно сказать, легендарный дебаггер JavaScript.