闭包
当一个函数被外部变量引用,该函数和作用域就形成闭包
function A() {
var count = 0;
function B() {
count ++;
console.log(count);
}
return B;
}
var C = A();
C();// 1
C();// 2
C();// 3
函数外是无法访问函数内的变量,当我们调用A的时候函数B返回来,并且把当前作用域的变量保存下来,可以继续在外部使用。
function makeAdder(x) {
return function(y) {
return x + y;
};
}
var add5 = makeAdder(5);
var add10 = makeAdder(10);
console.log(add5(2)); // 7
console.log(add10(2)); // 12
add5和add10是两个闭包,他们分别有自己的词法作用域,互不干涉。
<ol>
<li>第一项</li>
<li>第二项</li>
<li>第三项</li>
<li>第四项</li>
</ol>
<script>
var lis = document.getElementsByTagName('li');
for(var i = 0; i < lis.lengthl; i++) {
lis[i].onclick = function() {
console.log(i);
}
}
</script>
lis[i].onclick是一个闭包函数,四个lis[i]闭包共享同一个词法作用域,当点击之前已经循环结束,所以i变为4,输出全部为4
解决方案1
<script>
var lis = document.getElementsByTagName('li');
for(var i = 0; i < lis.lengthl; i++) {
lis[i].onclick = function() {
return function(i) {
console.log(i);
}
}(i)
}
</script>
现在每个闭包lis[i].onclick都有自己的词法作用域,互不干涉
解决方案2
<ol>
<li>第一项</li>
<li>第二项</li>
<li>第三项</li>
<li>第四项</li>
</ol>
<script>
var lis = document.getElementsByTagName('li');
for(let i = 0; i < lis.lengthl; i++) {
lis[i].onclick = function() {
console.log(i);
}
}
</script>
let和const拥有快作用域
这个例子使用let而不是var,因此每个闭包都绑定了块作用域的变量,这意味着不再需要额外的闭包。