文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JavaScript中的闭包是怎样的

2023-06-22 03:50

关注

这篇文章给大家介绍JavaScript中的闭包是怎样的,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。

1. 闭包的概念

来看一般函数的执行和启发:

function stop() {            var num = 0;            console.log(num);        }        stop(); // 打印出来num是0        console.log(num); // 报错 函数未定义

此时,函数的外部无法访问函数内部的变量

 函数内部定义的变量不会一直存在,随着函数的运行结束而消失

闭包的概念:

是一个函数,这个函数有权访问另一个作用域中的变量。

另一种说法,当内部函数的生命周期大于外部函数的声明周期,而内部函数以某一种方式被外部作用域访问时,闭包就产生了。

来看如下闭包的代码和解释:

function fn() {            var num = 10;            // function fun() {            //     console.log(num);             // }            // return fun;            return function () {                console.log(num); // 10            }        }        var f = fn();        f();

我们可以拆解为几个部分:

fn函数里面有内部的返回值且就是一个函数。

return的这个函数内部打印了num变量。为什么能够打印num变量,原因在于作用域链的访问机制,下面会补充作用域和作用域链的知识点。

我们在外部用f变量接受了fn(),也就是接受了fn的返回值【内部函数】

紧接着调用f,也就是调用了fn里面的内部函数。最终能够打印10

知识点的补充:

1. 作用域:

变量在某个范围内起作用,超出了这个范围,就不起作用。这个范围就是作用域。作用域在函数的定义时就产生,而不是函数调用时产生的。

2. 作用域链:

一句话概括:根据【内部函数可以访问外部函数变量】,采用就近原则一层一层向上查找变量,这个机制就叫作作用域链。

函数A包含了函数B,那么函数B就是函数A的内部函数,

而内部函数如果要使用一个变量,首先看自己内部有没有这个变量,

如果没有,就会去紧挨着的上一级查找,【就近原则】

如果函数一层一层都找不到,最后才会去全局变量下面找。

var a = 1;        var b = 11;        function fn1() {            var a = 2;            var b = '22';            fn2();            function fn2() {                var a = 3;                fn3();                function fn3() {                    var a = 4;                    console.log(a); // 4                    console.log(b); // '22'                }            }        }        fn1();

3. 垃圾回收机制

可以参考这位大哥对于JS垃圾回收机制的描述:

//www.yisu.com/article/229425.htm

我们结合这三个概念看闭包的作用

2. 闭包的作用:

我们把函数A叫作外层的函数,这个函数内部有一个函数B。

外部用一个变量f接受函数A的返回值【函数B】

而函数A作用域的变量叫作num

能够在函数的外部访问函数内部的变量【搭建外部访问内部作用域的通道】

原理:上面其实有解释过。

第一要理解,作用链的原理看上面。函数B能够调用函数A的变量num

第二要理解,首先函数A的返回值是函数B【内部函数】,其次这个返回值要在函数外部用变量f接受,接受以后就能够调用函数B,函数B就会访问函数A的变量num。而这个内部函数B就是闭包函数啦。

能够延长函数内部变量的生命周期。

第一个作用带来第二个作用。js的变量存在垃圾回收机制,如果函数执行完毕,变量会被清除,内存也会消除。可是如果利用闭包,变量可以不被立即清除。

原因是,外部的变量f接受了一个函数A的内部函数B,而这个内部函数访问了函数A作用域的变量num,只要函数B执行且变量f一直存在,那么变量num就会一直存在。不会因为函数A的执行结束就消失。

参考了下面的文章,讲的非常详细,推荐看。

JavaScript闭包详解

3. 闭包示例

后面会补充闭包的一些应用。

我们要想起什么场合用闭包,闭包不能滥用。

3.1 点击li,输出当前li的索引号

<ul class="nav">        <li>榴莲</li>        <li>臭豆腐</li>        <li>鲱鱼罐头</li>        <li>大猪蹄子</li>    </ul>    <script>        // 闭包应用-点击li输出当前li的索引号        // 1. 我们可以利用动态添加属性的方式        var lis = document.querySelector('.nav').querySelectorAll('li');        for (var i = 0; i < lis.length; i++) {            lis[i].onclick = function () {                console.log(i); // 四个4            }        }    </script>

原理:上图这样写,打印出来的i永远都是4。原因是,此时首先是非严格模式,在非严格模式下,for循环是同步执行任务,而按钮点击再执行是异步任务,同步执行完毕,i加到了4.再执行异步任务打印i,都是4。

改法1:用闭包

for循环生成四个立即执行函数

立即执行函数是闭包的一种应用。立即执行函数里面的所有函数包括【点击 回调】函数都可以使用立即执行函数的传递的形参。

for (var i = 0; i < lis.length; i++) {            (function (i) {                // console.log(i);                lis[i].onclick = function () {                    console.log(i);                 }            })(i);        }

改法2:var--->let

点击对应小li,打印i是对应索引号。使用let是ES6语法,此时for有块级作用域

var lis = document.querySelector('.nav').querySelectorAll('li');        for (let i = 0; i < lis.length; i++) {            lis[i].onclick = function () {                // console.log(i);                console.log(i);            }        }

改法3:用设置自定义属性index的方法

var lis = document.querySelector('.nav').querySelectorAll('li');        for (var i = 0; i < lis.length; i++) { // 注意这里是var不是let            lis[i].index = i; // 注意这里是lis[i]不是this.index,此时没有点击,哪里来的this            lis[i].onclick = function () {                console.log(this.index);            }        }

关于JavaScript中的闭包是怎样的就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-后端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯