JS 是作为一名合格的前端程序猿必不可少的技能之一. JS 涉及到的知识点又是相当的复杂. 闭包是让初学者头疼的一个知识点. 下面是我对闭包的理解, 希望可以帮助到一些朋友.
前提
想要搞懂闭包, 首先需要了解 JS 的变量作用域
全局变量和局部变量
- <script>
- var GlobalVarOne = 'global var one' // 全局作用域
- function scope(){
- var arrScope = ['yang','tong','li'] // 局部作用域
- GlobalVarTwo = "global var two" // 全局变量
- Windows.GlobalVarThree = "global var three" // 全局变量
- for(var i=0;i<arrScope.length;i++){ // 变量 i 是局部作用域
- console.log(arrScope[i])
- }
- console.log(arrScope)
- }
- scope()
- </script>
在函数内部使用 var 或 let 定义的变量都是局部变量, 如果没有使用 var,let,Windows 定义的变量会造成变量的提升, 成为全局变量.
全局变量一般使用 console.log(Windows. 变量名) 可以输出值
JS 变量访问特点
函数内部可以访问全局变量, 但是函数外部不能访问函数内部的局部变量
- <script>
- var GlobalVarOne = 'global var one' // 全局作用域
- function scope(){
- var arrScope = ['yang','tong','li'] // 局部作用域
- GlobalVarTwo = "global var two" // 全局变量
- Windows.GlobalVarThree = "global var three" // 全局变量
- for(var i=0;i<arrScope.length;i++){ // 变量 i 是局部作用域
- console.log(arrScope[i])
- }
- console.log(GlobalVarOne) // 输出 global var one
- }
- scope()
- console.log(Windows.GlobalVarThree) // 输出 global var three
- console.log(arrScope) //error:arrScope is not defined
- </script>
在上述代码中 console.log(arrScope) 报错, 原因就是 arrScope 是 scope 函数的局部作用域, 在函数外部不能访问. 而 console.log(GlobalVarOne) 可以正常输出, 是因为 GlobalVarOne 是全局变量, 在函数内部是可以访问到的.
概念
闭包: 有权访问另一个函数作用域中的变量的函数 (JavaScript 高级程序设计)
- <script>
- function outer() {
- var a = '变量 1'
- }
- console.log(a) //error
- </script>
上述代码中, 由于 a 变量是 outer 函数的局部变量, 在函数外部我们没有办法访问到 a 变量, 那我们怎么做才能访问到 a 变量呢. 这个时候就用到了闭包函数, 将 a 变量封装到一个函数中, 将其 return 出来.
- <script>
- function outer() {
- var a = 'local var'
- var inner = function(){
- console.log(a)
- }
- return inner //inner 就是闭包函数, 能够访问到 outer 函数的作用域
- }
- outer()() // 输出 local var
- </script>
个人理解 --- 闭包函数是为了实现函数外部能够访问函数内部的局部变量而存在的, 闭包函数其实就是链接函数内部与函数外部的桥梁.
作用
1. 可以读取函数自身以外的变量 (沿着作用域链寻找)
2. 可以让函数内部的变量始终存在于内存中, 不被垃圾回收机制销毁.
弊端
JS 存在销毁机制, 当函数执行完以后, 函数以及函数中的变量会被垃圾回收机制销毁, 但是闭包函数中存在函数内部的局部变量, 所以函数执行完以后不会被销毁, 会一直存在于内存中, 导致内存消耗过大, 同时还存在内存泄露的风险, 所以要慎用闭包函数.
来源: http://www.jianshu.com/p/4fe1fbc963a4