什么是闭包
函数即使脱离了它原本所在的词法作用域,也能够访问在词法作用定义的变量。因为函数被return出去了,没有执行一直持有函数的执行期上下文,然后就形成了闭包。闭包 = 执行环境 + 函数
这个函数 a 可以放在别的文件里面,然后得到的 b 函数,不管你在什么时候调用,都会正确打印「hello,闭包」,一般的 a 函数执行完,hello 变量就会被释放,但是在闭包里面,这个 hello 直到 b 函数执行之前,hello 都不会被释放。应用场景太多了,定时器、防抖按钮 什么的都需要用到闭包,下面我们看看应用场景
应用闭包的主要场合:
定时器

大家很容易就想到输出5个5
例一:函数每个一秒返回一个5
for (var i = 0; i < 5; i++) {setTimeout(function () {console.log(i)}, 1000 * i)}
上面可以简写为如下:
for (var i = 0; i < 5; i++) {var temp = function () {console.log(i)}setTimeout(temp , 1000 * i)}temp()
例二:每隔1秒返回一个undefine
for (var i = 0; i < 5; i++) {setTimeout(function (i) {console.log(i)}, 1000 * i)}
上面可以简写为如下:
for (var i = 0; i < 5; i++) {var temp= function (i) {console.log(i);}setTimeout(temp, i * 1000);}temp()
例三:结果是立即输出0,1,2,3,4,
for (var i = 0; i < 5; i++) {setTimeout((function(i) {console.log(i);})(i), i * 1000);}

如何模拟定时器的方式输出:
如何输出01,2,3,4,呢?可以考虑立即执行函数或者let的块级作用于的方式解决

设计私有的方法和变量。(团队合作可以封装代码互不影响)
任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数外部访问这些变量。私有变量包括函数的参数、局部变量和函数内定义的其他函数。
把有权访问私有变量的公有方法称为特权方法(privileged method)。
function closure(){var age =22;var resetAge=function(){age =20}var setAge = function (newAge) {age = newAge}var getAge = function(){console.log(age)return age}var obj ={resetAge: resetAge,setAge: setAge,getAge: getAge}return obj}let privateData = closure();privateData.getAge();privateData.setAge(29)privateData.getAge();privateData.resetAge();privateData.getAge();
简化代码如下:
function closure() {var age = 22;//特权方法return obj = {resetAge: function () {age = 20},setAge: function (newAge) {age = newAge},getAge: function () {console.log(age)return age}}}let privateData = closure();privateData.getAge();privateData.setAge(29)privateData.getAge();privateData.resetAge();privateData.getAge();
闭包缺点:内存泄漏
闭包会引用包含函数的整个变量对象,如果闭包的作用域链中保存着一个HTML元素,那么就意味着该元素无法被销毁。所以我们有必要在对这个元素操作完之后主动销毁。
闭包中的this对象

在上面这段代码中,obj.getName()()实际上是在全局作用域中调用了匿名函数,this指向了window。
这里要理解函数名与函数功能是分割开的,不要认为函数在哪里,其内部的this就指向哪里。
window才是匿名函数功能执行的环境。
如果想使this指向外部函数的执行环境,可以这样改写:
https://juejin.im/post/5c12598851882565422292f8
https://segmentfault.com/q/1010000009490850
https://www.cnblogs.com/echolun/p/11481991.html
