JavaScript таймеры с использованием функций и области видимости

JavaScript таймеры с использованием функций и области видимости

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

 

С чего мы обычно начинаем

Если вы когда-либо программировали на JavaScript, то скорее всего свой первый таймер вы создавали примерно следующим образом (вполне вероятно, что точно также пишут новички в JavaScript):

setTimeout("setBGColor()", 1000);
function setBGColor () {
	document.body.style.backgroundColor = "#f00";
}

Вроде бы здесь все хорошо, но если вы не начнете проверять ваш JavaScript код, например, с помощью инструмента JSLint, то вы быстро поймете, что использование строковых аргументов в функции setTimeout не рекомендуется (это также относится и к функции setInterval). Вместо этого лучше использовать функции. Дело в том, что при работе со строковыми параметрами, вам нужно объединять строки, точно так же, как выражения для eval, и это является небезопасным с точки зрения безопасности и стабильности работы.

 

Используем функцию в качестве параметра

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

setTimeout(function () {
	document.body.style.backgroundColor = "#f00";
}, 1000);

Вместо анонимной функции внутри вызова setTimeout, мы можем так же использовать указатель на функцию:

setTimeout(setBGColor, 1000);
function setBGColor () {
	document.body.style.backgroundColor = "#f00";
}

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

 

Работаем с переменными и ссылками

Приведенный выше код выглядит довольно хорошо, но что если мы захотим применить данный стиль к любому элементу, вызывая данную функцию? И даже захотим устанавливать цвет во время исполнения?

Для простоты, давайте вызовем функцию сразу же, как только загрузится window:

window.onload = function () {
	setElmBGColor.call(document.body, "#ff0");
};

Как вы видите, мы вызываем функцию в контексте определенного элемента (в данном случае document.body), используя метод call и также устанавливаем нужный нам цвет: “#ff0″ (#ff0 – это желтый цвет, для тех кто не умеет читать hex-код :-)).

 

setElmBGColor – с использованием строковых параметров

Если для реализации функции setElmGBColor мы будем использовать строку в функции setTimeout, то получим следующее:

function setElmBGColor (bgColor) {
	currentElm = this;
	setTimeout("currentElm.style.backgroundColor = '" + bgColor + "'", 1000);
}

Заметим, что переменная currentElm должна быть глобальной (ключевое слово var впереди опущено), т.к. функция setTimeout исполняется в глобальном контексте, т.е. в контексте объекта window (запомните, дети, глобальные переменные – это плохо). Также, приходится иметь дело с составлением строк, что небезопасно, как уже отмечалось выше.

 

setElmBGColor – с использованием функции и области видимости

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

function setElmBGColor (bgColor) {
	var currentElm = this;
	setTimeout(function () {
		currentElm.style.backgroundColor = bgColor;
	}, 1000);
}

 

setElmBGColor – с использованием функции с областью видимости и замыканием

Наш код будет более изящным, если мы будем использовать область видимости и замыкание. В результате, мы избавимся от переменной currentElm, и в качестве параметра функции, используемой при вызове setTimeout, мы будем использовать только контекст, в котором мы находимся:

function setElmBGColor (bgColor) {
	setTimeout(function (elm) {
		return function () {
			elm.style.backgroundColor = bgColor;
		};
	}(this), 1000);
}

 

Масштабируемое и удобное решение

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

setElmBGColor.call(document.body, "#ff0");

на этот:

setElmBGColor.call(document.getElementById("container"), "#00f");

и он тут же будет работать. Получилось довольно неплохо, не так ли? 🙂

 

Заключение

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

Удачного скриптинга! 🙂

 

Оригинал статьи JavaScript timers – using functions and scope (англ.)

Читайте также: