什么是闭包
函数即使脱离了它原本所在的词法作用域,也能够访问在词法作用定义的变量。因为函数被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