JS中的闭包
来源:互联网 发布:淘宝客推广员 编辑:程序博客网 时间:2024/06/12 21:47
对闭包的开始的认识是这样的:在函数A中嵌套定义的函数B,会将函数A中的局部变量“包起来”,这样在函数B执行的时候,即可以访问到函数A中的变量值。比如:
function A(){ var aLocal = 3; return function(){ console.log(aLocal); }}var B = A();B();//输出3
再抽象点定义就是,函数执行时可以访问在其定义时所处局部环境中的变量。这样理解了很长一段时间,也没觉的不妥,因为基本可以解释实际代码执行的效果。直到遇到这样一段:
var arr = [];function A(){ for(var i = 0;i < 10;i++){ arr[i] = function(){ console.log(i); } }}arr[6];//输出9;
按照之前的理解,arr[6]在定义时其所处局部环境变量中i值为6,为何结果是9呢?如何才能实现预期的效果呢?
var arr = [];function A(){ var temp = function(i){ return function(){ console.log(i); } } for(var i = 0;i < 10;i++){ arr[i] = temp(i); }}arr[6];//输出6;
如何从根本上理解呢?这就要理解js函数的作用域。函数执行时能访问哪些变量,是由函数的作用域决定的,若变量在当前函数的作用域中,则可访问,反之不可访问。
作用域可以理解为一个对象(键值对、哈希表…)。作用域中每个可访问的变量名都是该对象的一个键。js的函数的作用域不是一个单独的作用域对象构成的,而是作用域链,即由多个作用域对象依次串联。
函数执行中要访问一个变量时,先从最近的一个作用域对象中查找,若找不到则从上一个作用域对象中查找,直到找到该变量定义或找完作用域链上的所有作用域对象。
那么作用域链是如何形成的呢?首先,函数被定义时所处的作用域链(全局函数被定义时作用域链中只有全局对象,比如window。在函数A中嵌套定义的函数B被定义时所处的作用域链即函数A执行时的作用域链)将作为函数的初始作用域链被函数保存。其次,当函数执行时,形参及函数内的局部变量又构成了一个作用域对象,并被拼接到初始作用域链中。至此形成函数执行时完整作用域链。
据此分析代码2,当函数A执行时,A的形参(无)和局部变量(i)形成了A的作用域对象SA(省略描述A执行时完整作用域链),定义arr[i]时,arr[i]会将SA作为初始作用域链保存,无论i是几,arr[i]保存的初始作用域对象都是SA,故在arr[i]执行时,均在SA中找到变量i的定义,而此时SA中i的值为9;
据此分析代码3,每次定义arr[i],都是通过一次temp函数的执行。每次temp函数执行时都形成一个执行时作用域对象(由形参i构成)Si,Si作为初始作用域链被arr[i]保存,所以,arr[i]中保存的Si是不同的对象,每个对象中i的值都是temp执行时的形参值。
ES6中增加块作用域的概念后,作用域对象不仅限于函数执行时形参和局部变量形成的对象,还会有更小力度的块作用域对象。但是作用域链的概念和闭包形成的原理还是一致的。
- js中的闭包
- Js中的闭包
- js中的闭包
- js中的闭包
- JS 中的闭包
- js中的闭包
- JS中的闭包
- JS中的闭包
- js中的闭包
- JS 中的闭包
- JS中的闭包
- JS中的闭包
- js中的闭包
- js中的闭包
- js中的闭包
- js中的闭包
- JS中的闭包
- js 中的闭包
- 关于iOS中AES加密和base64编码的理解
- Zookeeper伪分布式安装
- 第六周项目4静态时间类
- centos6.4 安装R语言3.2.2
- JSP连接数据库实现注册登录(附带上传头像)
- JS中的闭包
- 第三周4(3)年龄几何
- 第5周项目3-时间类
- 第5周项目2-游戏中的角色类
- 贝叶斯公式与mahout贝叶斯分类器
- 迅雷、QQ旋风-链接自动转换(Download link conversion)
- C++课堂实验3
- iOS 获取当前时间
- 编译hadoop2.6