JS闭包的作用与优缺点[通俗易懂]

JS闭包的作用与优缺点[通俗易懂]一、什么是闭包闭包是指一个函数和对其周围状态(lexicalenvironment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。简单来说就是指有权访问另一个函数作用域中变量的函数。举个例子:functionfn(){varnum=10;functionfun(){console.log(num);}fun();}fn();这就是一个闭…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全家桶1年46,售后保障稳定

一、什么是闭包

        闭包是指一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包closure)。

        简单来说就是指有权访问另一个函数作用域中变量的函数。

举个例子:

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

Jetbrains全家桶1年46,售后保障稳定

这就是一个闭包了。fun 这个函数作用域访问了另外一个函数 fn 里面的局部变量 num。

二、闭包作用

        在js作用域环境中访问变量的权利是由内向外的,内部作用域可以获得当前作用域下的变量并且可以获得包含当前作用域的外层作用域下的变量,反之则不能,也就是说在外层作用域下无法获取内层作用域下的变量,同样在不同的函数作用域中也是不能相互访问彼此变量的,那么我们想在一个函数内部也有权限访问另一个函数内部的变量该怎么办呢?闭包就是用来解决这一需求的。

来看下面一个例子:

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

一个简单地闭包。正常情况下我们无法在外面访问到num这个变量。但通过闭包我们就可以让fn 外面的作用域访问fn内部的局部变量。只需要这么写:

function fn() {
    var num = 10;
    function fun() {
        console.log(num);
    }
    return fun;//将fun函数当返回值返回
}
var f =fn();//接受这个返回值

上面代码执行时类似于(我说的是类似):

//类似于
var f = function() {
        console.log(num);
}
f();

返回的是函数,再调用函数,而这个函数在fn里面,这样就可以访问到里面的num了

所以说闭包的主要作用就是:延伸了变量的作用范围。

三、闭包的优缺点

举个简单地例子。实现点击li输出当前li的索引号时。

有时候就想当然了,不仔细思考犯这个错误(注意以下写法是错误的)

var lis = document.querySelector('ul').querySelectorAll('li');
for (var i = 0; i < lis.length; i++) {
        console.log(i);
}

因为for是同步任务,function是异步任务。所以最后输出的都是4。

因此正常书写利用动态添加属性的方式书写:

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

利用闭包书写:

立即执行函数IIFE  ()();  ,创建函数后就立即执行。

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

利用for循环创建了4个立即执行函数。

这样看来其实还是第一种方法更简单些。并不是说闭包一定是好的。

利用闭包书写,每一次循环都创建了一个i,不点击就不会销毁,这样很占用内存,造成内存泄漏。这就是闭包的缺点。当然闭包也有自己的用处,在某些情况下,想延长变量的使用范围我们就可以使用闭包了。

总结:

优点:

①保护函数内的变量安全 ,实现封装,防止变量流入其他环境发生命名冲突
②在内存中维持一个变量,可以做缓存(但使用多了同时也是一项缺点,消耗内存)。
③匿名自执行函数可以减少内存消耗。(function(){}){}

坏处:
 ①被引用的私有变量不能被销毁,增大了内存消耗,造成内存泄漏,解决方法是可以在使用完变量后手动为它赋值为null。

 ②其次由于闭包涉及跨域访问,所以会导致性能损失,我们可以通过把跨作用域变量存储在局部变量中,然后直接访问局部变量,来减轻对执行速度的影响。

总的来说

闭包:函数内部包裹函数,作用域链得不到释放,造成消耗内存。

四、闭包的应用

闭包应用-计算打车价格 

打车起步价13(3公里内),  之后每多一公里增加 5块钱.  用户输入公里数就可以计算打车价格,

如果有拥堵情况,总价格多收取10块钱拥堵费。

var car = (function () {
    var start = 13; // 起步价  局部变量
    var total = 0; // 总价  局部变量
    return {
        // 正常的总价
        price: function (n) { //n 公里数
            if (n <= 3) {
                total = start;
            } else {
                total = start + (n - 3) * 5
            }
            return total;
        },
        // 拥堵之后的费用
        yd: function (flag) {
            return flag ? total + 10 : total;
        }
    }
})();
console.log(car.price(5)); // 23
console.log(car.yd(true)); // 33

console.log(car.price(1)); // 13
console.log(car.yd(false)); // 13

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227280.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • HandlerThread原理分析、实战、最佳实践!

    HandlerThread原理分析、实战、最佳实践!本文我们将学习HandlerThread的实现原理,以及开发时,如何正确的使用它来实现我们的开发任务。HandlerThread源码分析设想这样一个场景:我们要在一个线程A中处理业务逻辑,在另一个线程B中,监听A的执行,并进行结果处理。这时我们使用HandlerThread就可以非常简单的实现该功能了。通常我们的线程交互场景,都是UI线程中启动子线程,并且由子线程完成工作任务,最终结果交给UI线程。现在我们的使用场景是,在子线程中监控其他线程的执行结果(这里的其他线程可以是另一个子线程,也可以是UI

    2025年7月15日
    5
  • 一种集各种优点于一身的技术面试方式–转「建议收藏」

    一种集各种优点于一身的技术面试方式–转

    2022年3月2日
    37
  • Pychram引入conda环境[通俗易懂]

    Pychram引入conda环境[通俗易懂]Pychram引入conda环境一、前言考虑到:①pycharm比Spyder功能全面,②anaconda的环境配置方便,这两个因素,所以想要在pycharm上引入condaenvironment,充分利用Anaconda的库函数。二、导入步骤1.创建一个project,并在File栏中,点击settings…,进入设置界面2.在setting界面下,找到当前工程,并选中其中的PythonInterpreter3.点击右上角的齿轮图表4.在弹出的会话框中,选中Add…5.在Ad

    2022年8月26日
    5
  • SPSS操作(四):系统聚类分析

    SPSS操作(四):系统聚类分析现用如下数据做系统聚类分析:将数据导入spss中,如图:步骤如下:①【分析】—-【分类】—-【系统聚类】②x2、x3、x4、x5、x6、x7、x8添加到变量,x1(即地区)添加到个案标注依据小技巧:添加变量的时候,可以单击【医疗机构床位数(张)】,然后按住shift键不松,鼠标单击【医院(个)】就可以选择多个变量一起添加③点击【统计】勾选【解的范围】,可以根据自己的需要选择最小聚类数和最大聚类数(这里我设置为2和5),然后点击【继续】④点击【图】,(这里我选择的是做系谱图

    2022年10月18日
    4
  • uIP中国的协议文件:Ch01

    uIP中国的协议文件:Ch01

    2021年12月17日
    55
  • [黑苹果系列] M910x完美黑苹果系统安装教程 – 4 安装&设置macOS系统 – System Install

    [黑苹果系列] M910x完美黑苹果系统安装教程 – 4 安装&设置macOS系统 – System Install在BIOS中设置U盘启动,然后经过一段跑码,可以进到MacOS的界面,之后进入安装界面,先选择磁盘工具然后选择磁盘工具->显示所有设备,即可看见左侧的物理磁盘名称选择所需要安装的盘,选择抹掉然后,填好磁盘名和格式为APFS,方案为GUID分区图,然后抹掉完成后退出磁盘工具,选择安装macOSBigSur点击继续和同意后,选择相应的磁盘,点击继续,等待安装然后会安装完后会开始跑码重启后继续安装,到设置界面大约要重启…

    2022年6月9日
    62

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号