闭包,可以说是对 执行上下文
、 词法作用域
的一个实际应用,它不是语言的基本性质,而是由基本性质引申出来的功能特性,一种奇技淫巧。
自己总结:闭包指的就是函数,它能够访问其作用域链上的属性。
mdn: 闭包是函数和声明该函数的词法环境的组合
解释:因为js采用词法作用域,在函数定义的时候,就决定了它能够访问到外部变量的范围;在函数运行的时候,不管它在什么地方被调用,其作用域不变
理论上的闭包:所有函数都是闭包。因为函数在创建的时候就将上层上下文的数据保存起来了
实践上的闭包:1. 内部函数从父函数中返回 2. 在代码中引用了自由变量
自由变量:在函数中使用,但是不是函数的参数,也不是函数的自由变量,即从上层上下文获取到的变量
引用 mqyqingfeng 大神的例子
var scope = "global scope";
function checkscope(){
var scope = "local scope";
function f(){
return scope;
}
return f;
}
var foo = checkscope();
foo();
执行过程
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = function () {
console.log(i);
};
}
data[0]();
data[1]();
data[2]();
为什么每次都输出3呢?
以往的理解:在每次函数执行的时候,for循环已经执行完了,此刻 i=3
为什么是这个样子呢?
答:当执行data[0]函数的时候,创建其执行环境,它的作用域链为
data[0]Context = {
Scope: [AO, globalContext.Vo]
}
因为他的AO并没有 i 值,它能够访问到的 i 是全局上下文中的 i ,这也说明了为什么for循环执行完了函数再执行,函数的值为什么是3。
改成闭包
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = (function (i) {
return function(){
console.log(i);
}
})(i);
}
data[0]();
data[1]();
data[2]();
当执行data[0]函数的时候,创建其执行环境,它的作用域链为
data[0]Context = {
Scope: [AO, 匿名函数.VO, globalContext.VO]
}
在data[0]函数的作用域链中存在i,也就是匿名函数的i,首先访问到的是匿名函数的i。
很多地方都用到闭包,以后有应用场景就总结在这里
相关文章:深入js-词法作用域 深入js-执行上下文