1. setTimeout сценариев закрытия приложения
Первая функция, переданная нативным setTimeout, не может принимать параметры, а эффекта передачи параметров можно добиться через замыкание
setTimeout(function(param){
alert(param)
},1000)
//通过闭包可以实现传参效果
function func(param){
return function(){
alert(param)
}
}
var f1 = func(1);
setTimeout(f1,1000);
2. Обратные вызовы для сценариев закрытия приложений
Мы определяем поведение, а затем связываем его с пользовательским событием (кликом или нажатием клавиши). Наш код обычно привязывается к событию как обратный вызов (функция, вызываемая при срабатывании события).
<body>
<p>哈哈哈哈哈哈</p>
<h1>hhhhhhhhh</h1>
<h2>qqqqqqqqq</h2>
<a href="#" id="size-12">12</a>
<a href="#" id="size-14">14</a>
<a href="#" id="size-16">16</a>
<script>
function changeSize(size){
return function(){
document.body.style.fontSize = size + 'px';
};
}
var size12 = changeSize(12);
var size14 = changeSize(14);
var size16 = changeSize(16);
document.getElementById('size-12').onclick = size12;
document.getElementById('size-14').onclick = size14;
document.getElementById('size-16').onclick = size16;
</script>
</body>
3. Переменные инкапсуляции сценариев закрытия приложений
Используйте замыкания для определения публичных функций, которые могут обращаться к приватным функциям и приватным переменным.
var counter = (function(){
var privateCounter = 0; //私有变量
function change(val){
privateCounter += val;
}
return {
increment:function(){ //三个闭包共享一个词法环境
change(1);
},
decrement:function(){
change(-1);
},
value:function(){
return privateCounter;
}
};
})();
console.log(counter.value());//0
counter.increment();
counter.increment();//2
- Общая среда создается в теле анонимной функции, которая выполняется немедленно.
- В среде есть локальная переменная и локальная функция, доступ к которым осуществляется через три общедоступные функции объекта, возвращаемого анонимной функцией.
Еще один пример обёртывания приватной переменной: создаём счётчик в JavaScript:
'use strict';
function create_counter(initial) {
var x = initial || 0;
return {
inc: function () {
x += 1;
return x;
}
}
}
результат операции:
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3
var c2 = create_counter(10);
c2.inc(); // 11
c2.inc(); // 12
c2.inc(); // 13
В возвращаемом объекте реализовано замыкание, которое несет в себе локальную переменную x, а переменная x вообще недоступна из внешнего кода. другими словами,Замыкание — это функция, несущая состояние, и ее состояние может быть полностью скрыто от внешнего мира.
4. Сценарий приложения закрытия привязывает событие щелчка к циклу узла.
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push(function () {
return i * i;
});
}
return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
В приведенном выше примере каждый раз в цикле создается новая функция, а затем три созданные функции добавляются в массив и возвращаются.
Вы можете подумать, что вызов f1(), f2() и f3() должен привести к1 4 9,
Но фактический результат таков:
f1(); // 16
f2(); // 16
f3(); // 16
Всем 16! Причина в том, что возвращаемая функция ссылается на переменную i, но выполняется не сразу. К тому времени, когда все три функции вернутся, переменная i, на которую они ссылаются, станет равной 4, поэтому окончательный результат равен 16.
При возврате замыкания следует помнить, что возвращаемая функция не ссылается ни на какие переменные цикла или переменные, которые изменятся позже.
Что делать, если необходимо сослаться на переменную цикла? Метод заключается в создании другой функции и использовании параметров функции для привязки текущего значения переменной цикла.Независимо от того, как переменная цикла впоследствии изменяется, значение, связанное с параметром функции, остается неизменным:
function count() {
var arr = [];
for (var i=1; i<=3; i++) {
arr.push((function (n) {
return function () {
return n * n;
}
})(i));
}
return arr;
}
var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // 1
f2(); // 4
f3(); // 9
Обратите внимание на использование синтаксиса «создать анонимную функцию и выполнить ее немедленно»:
(function (x) {
return x * x;
})(3); // 9
5. Непреднамеренное использование замыканий в ES6
Иногда замыкания появляются, когда вы их не ожидаете, и вы, вероятно, видели пример того, что мы называем частичным приложением, как показано в коде ниже.
let c = 4
const addX = x => n => n + x
const addThree = addX(3)
let d = addThree(c)
console.log('example partial application', d)
Если вы не используете стрелочные функции, эквивалентный код выглядит следующим образом:
let c = 4
function addX(x) {
return function(n) {
return n + x
}
}
const addThree = addX(3)
let d = addThree(c)
console.log('example partial application', d)
Мы объявляем общую функцию сложения addX, которая принимает один аргумент (x) и возвращает другую функцию.
Возвращаемая функция также принимает один аргумент и добавляет его к переменной x.
Переменная x является частью замыкания, и когда переменная addThree объявляется в локальном контексте, она присваивается определению функции и замыканию, содержащему переменную x.
Таким образом, когда addThree вызывается и выполняется, он может получить доступ к переменной x и переменной n из замыкания (переданных в качестве аргументов) и вернуть добавленную сумму.
В этом примере консоль напечатает число 7.
Ссылка на справочную статью: