• 《JavaScript权威指南》学习——js闭包


    序:闭包这个玩意啊~在很多没有代码块的语言中都会出现,已经成为大多程序员入门的一道坎,闭包让很多程序员觉得晦涩(事实上百度一下这个名词,真的说的很晦涩啊亲==|||),我第一次知道闭包这个名词是从《JavaScript权威指南》中读到的,当时还是2015年的3月份,我刚开始看寒假购买的书,前女友说这本书封面上的犀牛丑死了,我说“你懂啥!”==|||

    话不多说,经过一番回忆,我想起来闭包这个东西直到分手后的5个月里都没有搞清楚,某一天我在实验室写完了三段js代码对比后,我了悟了这本神书的讲的闭包思想!

    先来看下闭包的百度百科,且看(配图):

    闭包是可以包含自由(未绑定到特定对象)变量的代码块;这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。“闭包” 一词来源于以下两者的结合:要执行的代码块(由于自由变量被包含在代码块中,这些自由变量以及它们引用的对象没有被释放)和为自由变量提供绑定的计算环境(作用域)。

    在 Scala、Scheme、Common Lisp、Smalltalk、Groovy、JavaScript、Ruby、 Python、Go、Lua、objective c、swift 以及Java(Java8及以上)等语言中都能找到对闭包不同程度的支持。

     

    乍一看,百度说的神乎其神,什么代码块,什么局部变量,说白了,我们只要搞清js的代码的一点原理:作用域的释放和存在问题。

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现。

    闭包有三个特性:

    1.函数嵌套函数

    2.函数内部可以引用外部的参数和变量

    3.参数和变量不会被垃圾回收机制回收

     

    对比下面三段代码:

    且看看下面代码:

    //全局变量的应用和变化
    
    Var GLOBAL = 1          //全局变量
    
    function change_global(){
    
        var GLOBAL = 2;             //重新定义了GLOBAL作为局部变量,不加var则变成了引用全局变量
    
        alert(GLOBAL);
    
    }
    
    change_global();
    
    Alert(GLOBAL);

    浏览器显示:先2,后1。

    结论:验证了一点,函数改变了局部变量,但没有改变全局变量,但是一旦去掉了局部变量GLOBAL前面的var那么结果就是2,2。函数执行完后,函数的作用域链被销毁,随之局部变量被销毁了!全局变量要等到页面关闭(程序结束)被销毁

    如果很熟悉js语法和作用域链的,可以跳过上面的代码,我是为了说下面的代码!

    且看下面代码:

    //z是个普通的function,执行一次作用域链就被销毁
    
    var function z(t){
    
        var s=[1,2,3];              //局部变量s
    
        s.push(t);          //往s数组中添加数字
    
        return s;
    
    }
    
    z(4);   //执行后销毁这次
    
    z(5);   //执行后销毁这次
    
    alert(z(6));    //执行后销毁这次

     

    浏览器显示:1,2,3,6。

    结论:4,5呢?当然是因为前两次执行结束后函数被销毁了,所以最后只有6被添加进去了,充分证明了js执行函数在内存中的原理——执行完就销毁function中的一切!

    上面的话不完全对,真的是一切吗?

    且看下面代码:

    //x这是个闭包函数,结束后会被销毁,但是因为他返回了另一个函数,这个函数调用并返回了局部变量s,所以s不能被摧毁了,必须被保留下来!
    
    //x这是个闭包函数,结束后会被销毁,但是因为他返回了另一个函数,这个函数调用并返回了局部变量s,所以s不能被摧毁了,必须被保留下来!
    
    function x(){
    
        var s=[1,2,3];              //一样的局部变量s
    
        return function(t){
    
            s.push(t);      //一样往s中添加数字
    
            return s;
    
        };
    
    }
    
    var y=x();      //闭包赋值给y变量
    
    y(4);
    
    y(5);
    
    alert(y(6));

    浏览器显示:1,2,3,4,5,6。

    结论:function x()事实上是制作了一个只属于代码块环境的闭包,闭包中的s变量是不会因为这个x执行完成后被销毁,也不会因为返回的函数执行完后被销毁,即使这段代码全部执行完,s仍然保留在内存中,作用域链也仍然存在,知道程序结束(关闭浏览器)!所以注意:滥用闭包会导致内存不足的!

    为了更好的说明,销毁与不销毁的问题,我推荐下面这段代码

    //全局对象y,当中的变量:程序结束前永远不会销毁
    
    //函数中的局部对象在函数结束后也会像变量一样被销毁的
    
    var y={
    
        s:[1,2,3],          //对象中的变量
    
        //对象中的方法(类似于函数)
    
    add:function(t){
    
            this.s.push(t);
    
            return this.s;
    
        }
    
    }
    
    y.add(4);
    
    y.add(5);
    
    alert(y.s);

    浏览器显示:1,2,3,4,5,6。

    结论:用对象和闭包达到同样的效果,因为对象除非指定销毁,不然会存留在当前程序内存中!

    使用闭包有一个优点,也是它的缺点,就是可以把局部变量驻留在内存中,可以避免使用全局变量。全局变量在每个模块都可调用,这势必将是灾难性的。

     

  • 相关阅读:
    ASP.NET MVC 3 学习笔记系列之Music Store(1)
    sql 拆分 逗号 函数
    软件开发项目的人力资源管理 团队配置问题探讨
    从某失败项目中学到的经验教训
    需求为王
    信息系统项目管理师考试经验分享
    JSP中文乱码问题及编码知识详解
    详解java中instanceof各种的用法
    mvc开源项目
    asp.net服务组件自动事务处理
  • 原文地址:https://www.cnblogs.com/devilyouwei/p/6293106.html
Copyright © 2020-2023  润新知