JavaScript——以简单的方式理解闭包

  闭包,在一开始接触JavaScript的时候就听说过。首先明确一点,它理解起来确实不复杂,而且它也非常好用。那我们去理解闭包之前,要有什么基础呢?我个人认为最重要的便是作用域(lexical scope),如果对作用域和作用域链不理解的同学最好自己先去学一学,再回过头来,理解闭包,就更加轻松。

  下面便直接进入主题。

  我们知道一个函数是有作用域的,在函数内部定义的局部变量只有在函数内部才可以访问的到。一旦函数访问结束被销毁,局部变量随之也会销毁,无法通过任何方式再次访问局部变量,除了闭包。也就是说,我们可以通过闭包这一个方法,从函数的外部去访问到函数内部的变量,即使那个函数已经被销毁。没错,闭包最重要的用法就是,我们只提供某些接口去访问和修改局部变量,而外部是不能直接访问到局部变量的。

  说了那么多有关如何使用闭包,我们来看看闭包是长什么样子的。又到了举个栗子的环节,依然是最简单的people和name。

复制代码
var people = function(){
        var name = "Yika";
        var sayName = function(){
            return name;  //访问了people函数的局部变量name
        }
        var setName = function(newName){
            name = newName;  //访问了people函数的局部变量name
        }
        return{
            sayName: sayName,
            setName: setName
        }//返回一个对象
    }

    var p1 = people();        //函数return的是一个对象,这个对象里有两个函数sayName和setName
    console.log(p1.name);     //undefined.   name是people函数里的局部变量,而不是p1对象的属性,当然为undefined
    console.log(p1.sayName());//"Yika"
    p1.setName("Ruyi");       //通过setName函数修改局部变量name的值
    console.log(p1.sayName());//"Ruyi"
复制代码

  看完这个例子,想必对闭包多少有个了解啦,除了注释的内容,下面再做些补充。

  问:为什么局部变量name属性在people执行完之后,没有被销毁呢,反而数值还保存在内存中。

  答: 在例子中,函数注释那里专门写了(访问了people函数的局部变量name)。正是因为people函数里的sayName函数和setName函数访问了name属性,并且通过return传到了p1对象里,成了p1的两个方法。因为方法一直引用着people函数的局部变量,所以不会被消除,依然会在内存中。这样便形成了闭包,可以在函数外部访问到函数内部的局部变量。

  对此,我们可以换个更直观的写法。

复制代码
var people = function(){
        var name = "Yika";

        var obj = {
            sayName: function(){
                return name;
            },
            setName: function(newName){
                name = newName
            }
        };

        return obj;       //直观的返回对象
    }
//下面的结果是一样的。
复制代码

  当然闭包也不是一直那么好用,特别是在循环里。继续举例子

复制代码
<body>
    <input type="button"/>
    <input type="button"/>
    <input type="button"/>
    <input type="button"/>
    <input type="button"/>
    <input type="button"/>
    <input type="button"/>
    <script type="text/javascript">
        var oBtn = document.getElementsByTagName('input');
        for(var i = 0, len = oBtn.length; i < len; i++){
            oBtn[i].onclick = function(){
                alert("value = " + i);    //闭包陷阱的发生地!永远输出 value = 7
            }
        }
    </script>
</body>
复制代码

  当我们运行上面的代码的时候,我们是这样想的,循环一下按钮,并输出按钮所在的序号,但是我们得到的却永远是7。其实用我们之前讲的闭包会让变量的值一直保存在内存中的原理想一想,就应该懂了。当我们循环的时候按钮的点击事件时,是引用了for循环里的 i 变量。当所有按钮都绑定了点击事件后,i 的值也已经变成了7,当然所有的按钮输出的都是7啦!怎么解决这个问题也很好办的,但是我希望留下给大家思考。这里就说一下大致思路吧,我们可以在循环之外创建一个辅助函数,并让辅助函数return一个绑定当前 i 的函数。

  当然这里我也只是抛砖引玉的介绍了一下闭包,希望可以帮到大家浅显简单的了解闭包。

  还是那句话噢,有问题立即指正,我一定会立马检查更正,以免误导了大家!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip 【备注】 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用!有问题请及时沟通交流。 2、适用人群:计算机相关专业(如计科、信息安全、数据科学与大数据技术、人工智能、通信、物联网、自动化、电子信息等)在校学生、专业老师或者企业员工下载使用。 3、用途:项目具有较高的学习借鉴价值,不仅适用于小白学习入门进阶。也可作为毕设项目、课程设计、大作业、初期项目立项演示等。 4、如果基础还行,或热爱钻研,亦可在此项目代码基础上进行修改添加,实现其他不同功能。 欢迎下载!欢迎交流学习!不清楚的可以私信问我! 毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip毕设新项目-基于Java开发的智慧养老院信息管理系统源码+数据库(含vue前端源码).zip
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值