2019独角兽企业重金招聘Python工程师标准>>>
1. 变量作用域
要理解闭包,首先要先理解javascript变量的作用域 变量的作用域只有两种:全局变量 + 局部变量
全局变量:任何地方都可以访问(函数内部、外部) 局部变量:只能在变量所在函数及函数的子函数中访问 :fa-exclamation-circle:注意:变量声明如果不使用var关键字,那么他就是一个全局变量,即使是在函数内部定义
1.1 计算器困境:
希望计算器的值counter能够被修改,但是不希望被任意更改(只能+1) 全局变量实现:
var counter = 0;function add(){++counter;}add(); //1add(); //2add(); //3问题:counter的值可以被任意更改。
局部变量实现:
function add(){var counter = 0;++counter;}add(); //1add(); //1add(); //1问题:counter的值不能按照设想来正确输出。
javascript的闭包就可以解决该问题。
2. javascript内嵌函数
在javascript中,所有的函数均可以访问它们上层的作用域
function add(){var counter = 0;function plus(){++counter;}
}
上面代码中,plus函数在add函数内部,这使得add内部的所有局部变量都是对plus可见的,但是反过来却不行。 这就是javascript语言特有的【链式作用域】结构(chain scope)
如果我们能够在外部访问plus函数,那么这个【计算机困境】就能够解决了 所以,只要将plus函数作为add函数的返回值,就可以访问plus函数了, 也就可以通过plus函数,在add函数外部访问add函数局部变量了
================ 以上所说就是闭包。
3. javascript中的闭包
当函数a的内部函数b被函数a外的一个变量引用的时候,就创建了一个闭包。 闭包就是将函数内部和函数外部连接起来的一座桥梁
3.1 闭包的用途:
- 可以读取函数内部的变量
- 可以让函数内部变量的值始终保存在内存中
计算机困境可以更改为以下两种方式:
1:(建议)
var add = (function(){var counter = 0;return function plus(){return ++counter;}
})();add(); //1
add(); //2
add(); //32:
function add(){var counter = 0;return function plus(){return ++counter;}}var f1 = add(); f1(); //1f1(); //2f1(); //3
以上证明:局部变量counter一直在内存中, 并没有在函数执行完后自动清除。 why?????? because: --add是plus的父函数,而plus被赋给了一个全局变量,导致plus始终在内存中, 而plus函数依赖于add函数,所以add也一直在内存中,不会再结束后被GC回收。
3.2 getter/setter
function add(){var counter = 0;getCounter = function(){reutrn counter;}
}
注意add中的getCounter变量,因为没有使用var来声明,所以它是一个全局变量, 可以当做java中的getter来使用 :fa-hand-o-down:
public class add{private int counter = 0;public int getCounter(){return counter;}
}
3.3 闭包应该注意的问题
- 由于闭包使得函数中的变量,都被保存在内存中,内存消耗很大,所以不能滥用闭包。 否则会造成网页性能问题,甚至会内存泄漏。 解决方案:退出函数之前,将不使用的局部变量全部消除(变量的值为null即可)。
- 如果把函数当做Object使用,不要随便通过setter/闭包改变函数内部的变量值。