en.javascript.info/1-js/5-functions-closures/4-closures-usage/article.md
2015-03-22 19:14:01 +03:00

126 lines
4.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Локальные переменные для объекта
Замыкания можно использовать сотнями способов. Иногда люди сами не замечают, что использовали замыкания -- настолько это просто и естественно.
В этой главе мы рассмотрим дополнительные примеры использования замыканий и задачи на эту тему.
[cut]
## Счётчик-объект
Ранее мы сделали счётчик.
Напомню, как он выглядел:
```js
//+ run
function makeCounter() {
var currentCount = 1;
return function() {
return currentCount++;
};
}
var counter = makeCounter();
// каждый вызов возвращает результат, увеличивая счётчик
alert( counter() ); // 1
alert( counter() ); // 2
alert( counter() ); // 3
```
Счётчик получился вполне рабочий, но вот только возможностей ему не хватает. Хорошо бы, чтобы можно было сбрасывать значение счётчика или начинать отсчёт с другого значения вместо `1` или... Да много чего можно захотеть от простого счётчика и, тем более, в более сложных проектах.
**Чтобы добавить счётчику возможностей -- перейдём с функции на полноценный объект:**
```js
//+ run
function makeCounter() {
var currentCount = 1;
return { // возвратим объект вместо функции
getNext: function() {
return currentCount++;
},
set: function(value) {
currentCount = value;
},
reset: function() {
currentCount = 1;
}
};
}
var counter = makeCounter();
alert( counter.getNext() ); // 1
alert( counter.getNext() ); // 2
counter.set(5);
alert( counter.getNext() ); // 5
```
Теперь функция `makeCounter` возвращает не одну функцию, а объект с несколькими методами:
<ul>
<li>`getNext()` -- получить следующее значение, то, что раньше делал вызов `counter()`.</li>
<li>`set(value)` -- поставить значение.</li>
<li>`reset()` -- обнулить счётчик.</li>
</ul>
Все они получают ссылку `[[Scope]]` на текущий (внешний) объект переменных. Поэтому вызов любого из этих методов будет получать или модифицировать одно и то же внешнее значение `currentCount`.
## Объект счётчика + функция
Изначально, счётчик делался функцией во многом ради красивого вызова: `counter()`, который увеличивал значение и возвращал результат.
К сожалению, при переходе на объект короткий вызов пропал, вместо него теперь `counter.getNext()`. Но он ведь был таким простым и удобным...
Поэтому давайте вернём его!
```js
//+ run
function makeCounter() {
var currentCount = 1;
*!*
// возвращаемся к функции
function counter() {
return currentCount++;
}
*/!*
// ...и добавляем ей методы!
counter.set = function(value) {
currentCount = value;
};
counter.reset = function() {
currentCount = 0;
};
return counter;
}
var counter = makeCounter();
*!*
alert( counter() ); // 1
alert( counter() ); // 2
counter.set(5);
alert( counter() ); // 5
*/!*
```
Красиво, не правда ли? Получился полноценный объект, который можно вдобавок ещё и вызывать.
Этот трюк часто используется при разработке JavaScript-библиотек. Например, популярная библиотека [jQuery](http://jquery.com) предоставляет глобальную переменную с именем [jQuery](http://api.jquery.com/jQuery/) (доступна также под коротким именем `$`), которая с одной стороны является функцией и может вызываться как `jQuery(...)`, а с другой -- у неё есть различные методы, например `jQuery.type(123)` возвращает тип аргумента.
## Задачи на понимание замыканий