博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
闭包详解
阅读量:5270 次
发布时间:2019-06-14

本文共 2351 字,大约阅读时间需要 7 分钟。

前言: 想要了解闭包,首先要了解另一篇的文章。

1.闭包是什么?

内部函数在定义的词法作用域外被调用,就会产生闭包。

定义时所在的作用域不被垃圾回收机制自动回收。仍然保留在内存中。

缺点:

内部函数在外面每次被调用的时候,都会产生一个新的闭包。闭包导致大量内存不能被js引擎的垃圾回收机制释放。

从而造成网页性能问题。

解决办法:

使用块作用域。

上图中wait()执行后,相当于在timer的词法作用域之外调用timer函数。timer函数的词法作用域在setTimeout中,被wait创建的词法作用域嵌套。

timer函数可以访问到wait()作用域中的变量和内容。wait()作用域对于外部作用域来说是封闭的。timer函数有个涵盖wait(...)的作用域闭包。

⚠️IIFE虽然不是闭包,但是它具有闭包的性质。

 2. 如何解决闭包内存不被回收的问题

function process(data) {    // process}var someReallyBigData={
/*data*/};process(someReallyBigData);var btn = document.getElementById('my_button');btn.addEventListener("click", function click(evt) { console.log('==clicked==');}, /*capture=*/false);// click函数是监听事件的回调,它拥有涵盖全局作用域的闭包。 // 正常process执行完成后,后面不再使用占用大量内存数据结构someReallyBigData,可以被回收掉。// 但是因为闭包不可回收,它还会继续保存这个数据结构。 /********************解决方案*************************** function process(data) { // process}{ // 因为不在全局作用域中,完事就可以被销毁 var someReallyBigData={
/*data*/}; process(someReallyBigData);}var btn = document.getElementById('my_button');btn.addEventListener("click", function click(evt) { console.log('==clicked==');}, /*capture=*/false);

3. 循环和闭包

其实在定时器,事件监听,ajax请求等任务中的回调函数,其实都是在使用闭包。

for(var i =1; i<=5; i++) {    setTimeout(function timer() {        console.log(i);    }, 1000 * i);}// 这段代码本来想输入1-5,每秒一次,每次一个值// 实际情况是每秒输出一个值6,输入了5次。/**按照词法作用域分析,代码等同于下面*****/var i = 6;setTimeout(function timer() {    console.log(i);}, 1000);setTimeout(function timer() {    console.log(i);}, 2000);setTimeout(function timer() {    console.log(i);}, 3000);setTimeout(function timer() {    console.log(i);}, 4000);setTimeout(function timer() {    console.log(i);}, 5000);因为timer是回调函数,所以,console中的i是最后获取。

如果想要达到最初的目的,则需要每次取值的时候从自己的作用域取值,每次迭代的IIFE函数都有自己的作用域,最后取值的时候从各自的作用域取值。

for(var i = 1; i<=5;i++) {    (function IIFE(){        var j = i;        setTimeout(function timer() {            console.log(j);        }, 1000*j);     })()}// 等同于for(var i = 1; i<=5;i++) {    (function IIFE(j){        setTimeout(function timer() {            console.log(j);        }, 1000*j);     })(i)}

let实现的闭包块作用域;每次迭代都是一个新的作用域。

for(var i = 1; i<=5;i++) {      let j = i;  // 闭包的块作用域    setTimeout(function timer() {        console.log(j);    }, 1000*j); }// 等同于for(let i = 1; i<=5; i++) {    setTimeout(function timer() {        console.log(i);    }, 1000*i);   }

4. 闭包应用

 

转载于:https://www.cnblogs.com/lyraLee/p/11434901.html

你可能感兴趣的文章
[JS]递归对象或数组
查看>>
多线程《三》进程与线程的区别
查看>>
linux sed命令
查看>>
html标签的嵌套规则
查看>>
[Source] Machine Learning Gathering/Surveys
查看>>
HTML <select> 标签
查看>>
tju 1782. The jackpot
查看>>
湖南多校对抗赛(2015.03.28) H SG Value
查看>>
hdu1255扫描线计算覆盖两次面积
查看>>
hdu1565 用搜索代替枚举找可能状态或者轮廓线解(较优),参考poj2411
查看>>
bzoj3224 splay板子
查看>>
程序存储问题
查看>>
Mac版OBS设置详解
查看>>
优雅地书写回调——Promise
查看>>
android主流开源库
查看>>
AX 2009 Grid控件下多选行
查看>>
PHP的配置
查看>>
Struts框架----进度1
查看>>
Round B APAC Test 2017
查看>>
MySQL 字符编码问题详细解释
查看>>