js 作用域,作用域链,闭包
什么是作用域?
作用域是一种规则,在代码编译阶段就确定了,规定了变量与函数的可被访问的范围。全局变量拥有全局作用域,局部变量则拥有局部作用域。 js是一种没有块级作用域的语言(包括if、for等语句的花括号代码块或者单独的花括号代码块都不能形成一个局部作用域),所以js的局部作用域的形成有且只有函数的花括号内定义的代码块形成的,既函数作用域。
什么是作用域链?
作用域链是作用域规则的实现,通过作用域链的实现,变量在它的作用域内可被访问,函数在它的作用域内可被调用。
作用域链是一个只能单向访问的链表,这个链表上的每个节点就是执行上下文的变量对象(代码执行时就是活动对象),单向链表的头部(可被第一个访问的节点)始终都是当前正在被调用执行的函数的变量对象(活动对象),尾部始终是全局活动对象。
作用域链的形成?
我们从一段代码的执行来看作用域链的形成过程。
function fun01 () { console.log('i am fun01...'); fun02(); } function fun02 () { console.log('i am fun02...'); } fun01();
数据访问流程
如上图,当程序访问一个变量时,按照作用域链的单向访问特性,首先在头节点的AO中查找,没有则到下一节点的AO查找,最多查找到尾节点(global AO)。在这个过程中找到了就找到了,没找到就报错undefined。
关于闭包
1.什么是闭包?
函数对象可以通过作用域链相互关联起来,函数体内的数据(变量和函数声明)都可以保存在函数作用域内,这种特性在计算机科学文献中被称为“闭包”。既函数体内的数据被隐藏于作用于链内,看起来像是函数将数据“包裹”了起来。从技术角度来说,js的函数都是闭包:函数都是对象,都关联到作用域链,函数内数据都被保存在函数作用域内。
//闭包实例 function outerFun () { var outerV1 = 10 function outerF1 () { console.log('I am outerF1...') } function innerFun () { var innerV1 = outerV1 outerF1() } return innerFun //return回innerFun()内部函数 } var fn = outerFun() //接到return回的innerFun()函数 fn() //执行接到的内部函数innerFun()
此时它的作用域链是这样的:
3.闭包的好处及使用场景
js的垃圾回收机制可以粗略的概括为:如果当前执行上下文执行完毕,且上下文内的数据没有其他引用,则执行上下文pop出call stack,其内数据等待被垃圾回收。而当我们在其他执行上下文通过闭包对执行完的上下文内数据仍然进行引用时,那么被引用的数据则不会被垃圾回收。就像上面代码中的outerV1,放我们在全局上下文通过调用innerFun()仍然访问引用outerV1时,那么outerFun执行完毕后,outerV1也不会被垃圾回收,而是保存在内存中。另外,outerV1看起来像不像一个outerFun的私有内部变量呢?除了innerFun()外,我们无法随意访问outerV1。所以,综上所述,这样闭包的使用情景可以总结为:
(1)进行变量持久化。
(2)使函数对象内有更好的封装性,内部数据私有化。
function countFun () { var count = 0 return function(){ return count++ } } var a = countFun() a()//0
a()//1,变量count没有被回收
4.闭包的注意事项
由于闭包中的变量不会像其他正常变量那种被垃圾回收,而是一直存在内存中,所以大量使用闭包可能会造成性能问题。
参考:http://www.cnblogs.com/ivehd/p/scopechain.html
- js的闭包与作用域/作用域链
- js作用域,作用域链以及闭包
- JS高级知识(作用域,作用域链,闭包)
- 简述JS作用域、作用域链和闭包
- js重点浅谈(跨域,作用域和作用域链,闭包,原型和原型链继承)
- 理解js 的作用域链 原型链 闭包 词法分析
- [ JS 进阶 ] 闭包,作用域链,垃圾回收,内存泄露
- js 作用域和闭包1
- JS闭包作用及理解
- js作用域与闭包
- 你不得不知道的js之作用域链与闭包
- javscript闭包的准备工作 -- 作用域与作用域链
- 你不知道的JS---作用域和闭包
- 你不懂JS:作用域与闭包 第二章:词法作用域
- JS闭包之词法作用域
- js闭包的作用
- js——作用域和闭包
- js的作用域、作用域链、闭包
- js---07 js预解析,作用域---闭包
- Js作用域与作用域链详解