从两个函数来学习js闭包的概念
2017-09-19 16:31
218 查看
从两个函数来学习js闭包的概念
1.闭包:闭包是指有权访问另一个函数作用域中的变量的函数。
如下面f1()函数,通过return将自己内部的函数f2()返回,使得在f1()的外部,可以通过return的f2()函数来访问f1()函数内部变量n
在继续闭包的理解之前,需要了解下函数执行过程中发生的一些事情:
当某个函数被调用时,会创建一个执行环境(execution context)及相应的作用域链。
然后,使用 arguments 和其他命名参数的值来初始化函数的活动对象(activation object)。但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位,……直至作为作用域链终点的全局执行环境。
也就是说:函数在执行之前,都会创建一个新的执行环境,从result2()的返回值999可以看出来,他并不受nAdd()操作的影响。
无论什么时候在函数中访问一个变量时,就会从作用域链中搜索具有相应名字的变量。一般来讲,
当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象)。
但是,闭包的情况又有所不同。因为f1()return的函数f2包含了对f1函数内部定义的变量n的引用,所以变量n不会立即被回收。
下面这段函数执行结果为The Window
按照对闭包的初步了解,可能会认为执行object.getNameFunc()(),实际是在执行
那么再从作用域链逐层向上寻找变量时,会找到object中的name
但是却找到了全局变量var name = “The Window”;
那么理解的误区在哪呢?就是对作用域链中具体保存的内容理解有误。
作用域链中保存的内容为:
对于每一个执行环境,都会创建一个与之关联的作用域链。每个执行环境的作用域链的前端,始终都是该执行环境的变量对象,对于全局执行环境就相当于window对象,对于函数执行环境就相当于该函数的活动对象;对于全局执行环境,已经是根部,没有后续,对于函数执行环境,其作用域链的后续是该函数对象的[[scope]]属性里的作用域链。
上面描述简单来说,就是函数执行过程中对于变量的查找是沿着作用域链逐层向上寻找,作用域链内存放是该作用域的活动变量,那么活动变量又包含哪些呢?
在一个函数对象被调用的时候,会创建一个活动对象,首先将该函数的每个形参和实参,都添加为该活动对象的属性和值;将该函数体内显示声明的变量和函数,也添加为该活动的的属性。
也就是说保存了形参和实参,函数体内显示声明的变量和函数。从上面可以看出并不包含this对象,所以并不会逐层向上寻找到object的this对象。
那么为什么又会把this指向window呢,其实执行的最终形式是:
所以this指向函数的调用者window,最终this.name就指向了全局变量
如有不正确的地方,欢迎交流指正。
相关参考:
http://www.cnblogs.com/amy-fox/p/5856771.html
http://www.cnblogs.com/pssp/p/5216085.html
1.闭包:闭包是指有权访问另一个函数作用域中的变量的函数。
如下面f1()函数,通过return将自己内部的函数f2()返回,使得在f1()的外部,可以通过return的f2()函数来访问f1()函数内部变量n
function f1() { var n = 999; nAdd = function() { n += 1; }; function f2() { return n; } return f2; } var result1 = f1(); var result2 = f1(); alert(result1()); // 999 nAdd(); alert(result1()); // 1000 alert(result2()); // 999
在继续闭包的理解之前,需要了解下函数执行过程中发生的一些事情:
当某个函数被调用时,会创建一个执行环境(execution context)及相应的作用域链。
然后,使用 arguments 和其他命名参数的值来初始化函数的活动对象(activation object)。但在作用域链中,外部函数的活动对象始终处于第二位,外部函数的外部函数的活动对象处于第三位,……直至作为作用域链终点的全局执行环境。
也就是说:函数在执行之前,都会创建一个新的执行环境,从result2()的返回值999可以看出来,他并不受nAdd()操作的影响。
无论什么时候在函数中访问一个变量时,就会从作用域链中搜索具有相应名字的变量。一般来讲,
当函数执行完毕后,局部活动对象就会被销毁,内存中仅保存全局作用域(全局执行环境的变量对象)。
但是,闭包的情况又有所不同。因为f1()return的函数f2包含了对f1函数内部定义的变量n的引用,所以变量n不会立即被回收。
下面这段函数执行结果为The Window
var name = "The Window"; var object = { name: "My Object", getNameFunc: function() { return function() { return this.name; }; } }; alert(object.getNameFunc()()); //The Window
按照对闭包的初步了解,可能会认为执行object.getNameFunc()(),实际是在执行
function() { return this.name; }
那么再从作用域链逐层向上寻找变量时,会找到object中的name
但是却找到了全局变量var name = “The Window”;
那么理解的误区在哪呢?就是对作用域链中具体保存的内容理解有误。
作用域链中保存的内容为:
对于每一个执行环境,都会创建一个与之关联的作用域链。每个执行环境的作用域链的前端,始终都是该执行环境的变量对象,对于全局执行环境就相当于window对象,对于函数执行环境就相当于该函数的活动对象;对于全局执行环境,已经是根部,没有后续,对于函数执行环境,其作用域链的后续是该函数对象的[[scope]]属性里的作用域链。
上面描述简单来说,就是函数执行过程中对于变量的查找是沿着作用域链逐层向上寻找,作用域链内存放是该作用域的活动变量,那么活动变量又包含哪些呢?
在一个函数对象被调用的时候,会创建一个活动对象,首先将该函数的每个形参和实参,都添加为该活动对象的属性和值;将该函数体内显示声明的变量和函数,也添加为该活动的的属性。
也就是说保存了形参和实参,函数体内显示声明的变量和函数。从上面可以看出并不包含this对象,所以并不会逐层向上寻找到object的this对象。
那么为什么又会把this指向window呢,其实执行的最终形式是:
object.getNameFunc()() --> getNameFunc() --> window.getNameFunc()
所以this指向函数的调用者window,最终this.name就指向了全局变量
var name = "The Window";
如有不正确的地方,欢迎交流指正。
相关参考:
http://www.cnblogs.com/amy-fox/p/5856771.html
http://www.cnblogs.com/pssp/p/5216085.html
相关文章推荐
- JavaScript高级程序设计(第2版) 学习笔记:(二)js函数作用域与闭包
- 一切皆对象之两个方法概括js,无函数签名(无多态),原型,闭包,封装,引用类型,继承……
- 原来 JS 也支持跟 Lua 语意一样的内嵌函数的闭包概念
- 原来 JS 也支持跟 Lua 语意一样的内嵌函数的闭包概念
- js学习之函数表达式及闭包
- JavaScript学习总结二:js闭包(Closure)概念
- JavaScript学习总结二:js闭包(Closure)概念
- js学习(一)-对象和函数概念
- JavaScript学习记录总结(六)——js函数闭包特性
- js闭包,匿名函数概念
- JS高级程序设计学习笔记之第三章基本概念(语法,数据类型,流控制语句,函数)——查漏补缺
- Js中的闭包与自执行函数
- [学习日记]vb.net里的两个重要的时间函数
- JavaScript权威设计--命名空间,函数,闭包(简要学习笔记十二)
- JavaScript总结学习一:js中构造函数与普通函数的区别
- JS闭包的概念
- Swift学习笔记 - 函数与闭包
- Python:通过计算阶乘来学习lambda和reduce这两个函数的使用
- js学习笔记_闭包
- HTML5+CSS3+JS学习笔记-8-使用JS及函数来制作表格