一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。
function books(){
var book = '书包里的书本';
return function(){
console.log(book);
}
}
var bag = books();
bag();
// 匿名函数执行上下文 = {作用域链: {匿名函数变量对象 + books变量对象 + 全局变量对象}, {变量对象: }}
// books执行上下文 = {作用域链: {books变量对象 + 全局变量对象}, {变量对象: book}}
// 全局执行上下文 = {作用域链: {全局变量对象}, {变量对象: books, bag}}
for(var i = 0; i < 5; i++){
(function(x){
console.log(x++);
})(i);
}
console.log(i);
// 立即执行函数执行上下文 = {作用域链: {立即执行函数变量对象 + 全局变量对象}, {变量对象: x}}
// 全局执行上下文 = {作用域链: {全局变量对象}, {变量对象: i}}
for(var i = 0; i < 5; i++){
setTimeout(function(){
console.log(i++);
});
}
console.log(i);
// 输出为 5 5 6 7 8 9
for(var i = 0; i < 5; i++){
(function(x){
setTimeout(function(){
console.log(x);
},4000)
})(i)
}
console.log(i);
// 输出为 5 0 1 2 3 4
<!DOCTYPE html>
<html>
<script>
var b = 'boy';
console.log(b);
function fighting(){
console.log(a);
console.log(b);
if(a === 'apple'){
a = 'Alice';
}else{
a = 'Ada';
}
console.log(a);
var a = 'Andy';
middle();
function middle(){
console.log(c++);
var c = 100;
console.log(++c);
samall();
function samall(){
console.log(a);
}
}
var c = a = 88;
function bottom(){
console.log(this.b);
b = 'baby';
console.log(b);
}
bottom();
}
fighting();
console.log(b);
</script>
</html>