# 闭包练习
# 练习1:
如下代码输出多少?如果想输出3,那如何改造代码?
var fnArr = [];
for (var i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i
};
}
console.log( fnArr[3]() ) // 10
输出10
fnArr[3]() 执行匿名函数 function(){ return i} ,函数内部无i,for循环内部无作用域,匿名函数作用域为全局作用域,for循环执行完毕后i变为10,所以输出i=10
- 方法1
var fnArr = []
for (var i = 0; i < 10; i ++) {
fnArr[i] = (function(j){
return function(){
return j
}
})(i)
}
console.log( fnArr[3]() ) // 3
//等价于
fnArr[3] = (function(j){
return function(){
return j
}
})(3)
//继续简化
var a = (function fn(j){
return function(){
return j
}
})(3)
a()
//相当于a等于立即执行函数,继续简化
function fn(j){
return function(){
return j
}
var a = fn(3)
//继续
function fn(j){
function f(){
return j
}
return f
}
var a = fn(3)
- 方法2
var fnArr = []
for (var i = 0; i < 10; i ++) {
(function(i){
fnArr[i] = function(){
return i
}
})(i)
}
console.log( fnArr[3]() ) // 3
- 方法3
var fnArr = []
for (let i = 0; i < 10; i ++) {
fnArr[i] = function(){
return i
}
}
console.log( fnArr[3]() ) // 3
# 练习2
如下代码输出多少?如何连续输出 0,1,2,3,4
for(var i=0; i<5; i++){
setTimeout(function(){
console.log('delayer:' + i )
}, 0)
}
delayer:5
delayer:5
delayer:5
delayer:5
delayer:5
setTimeout将当前函数加到任务队列,待for循环结束后执行任务队列;当前作用域无i,上级i=5,所以输出5次delayer:5
- 方法1:
for(var i=0; i<5; i++){
(function(j){
setTimeout(function(){
console.log('delayer:' + j )
}, 0)
})(i)
}
//等价于
function fn(j){
var j = arguments[0]
setTimeout(function(){
console.log('delayer:' + j )
}, 0)
}
fn(i)
- 方法2
for(var i=0; i<5; i++){
setTimeout((function(j){
return function(){
console.log('delayer:' + j )
}
}(i)), 0)
}
# 练习3:
如下代码输出多少?
function makeCounter() {
var count = 0
return function() {
return count++
};
}
var counter = makeCounter()
var counter2 = makeCounter();
console.log( counter() ) // 0
console.log( counter() ) // 1
console.log( counter2() ) // 0
console.log( counter2() ) // 1
counter与counter2指向不同对象,作用域不同。