zoukankan      html  css  js  c++  java
  • 【《你不知道的JS(上卷①)》】五、作用域闭包

    五、作用域闭包:

    ​ 闭包不是神奇的魔法,它只是遵循我们前几章一直介绍的 词法作用域书写代码的自然结果。

    ​ 闭包是由函数以及声明该函数的词法环境组合而成的。该环境包含了这个闭包创建时作用域内的任何局部变量。

    一)、回调函数与闭包:

    • 回调函数,将一个函数的引用作为参数传递给另一个函数。
    function wait(meesage) {
    	setTimeout(function timer() {
    		console.log(meesage);
    	}, 1000);
    }
    wait("Hello, closure!")
    

    ​ 无论何时何地,如果将函数(访问他们各自的词法作用域)当作第一级的值类型并到处传递,就可以看到闭包的存在。在定时器、事件监听器、Ajax请求、跨窗口通信等异步或同步任务中,只要使用了回调函数,实际上就是在使用闭包。

    二)、循环与闭包:

    // 使用var
    for (var i = 1; i <= 5; i++) {
    	setTimeout(function timer() {
    		console.log(i);
    	}, i * 1000)
    } // 6 6 6 6 6 
    
    // 使用let
    for (let i = 1; i <= 5; i++) {
    	setTimeout(function timer() {
    		console.log(i);
    	}, i * 1000)
    } // 1 2 3 4 5
    

    ​ 比较上面两段代码与输出结果。发现使用var在循环中声明变量不能达到我们想要的效果。这是因为尽管每次循环都定义了一个新的函数,但是对于这些函数,是共享同一个作用域的,因此i也是相同的。而使用let,会在每次迭代时都创建一个新的作用域。并且使用let会让i这个变量在每次迭代都会声明,且会使用上一个迭代结束时的值来初始化这个变量。

    三)、模块模式:

    ​ 在许多面向对象语言(如Java)中,都支持将方法声明为私有,即只能被同一个类中的方法调用。在JavaScript中并没有这种原生支持。我们可以使用闭包来模拟私有方法,这种方式也被称作 模块模式

    ​ 这种方式不仅有利于限制对代码的访问:还提供了管理全局命名空间的强大能力,避免非核心的方法弄乱代码的公共接口部分。

    var foo = (function CoolModule() {
      var something = "cool";
      var another = [1, 2, 3];
    
      function doSomething() {
        console.log(something);
      }
    
      function doAnother() {
        console.log(another.join("!"));
      }
    
      return {
        doSomething: doSomething,
        doAnother: doAnother
      }
    
    })();
    
    foo.doSomething(); // cool
    foo.doAnother(); // 1!2!3
    

    ES6中的模块机制:

    ​ ES6中为模块增加了一级语法支持。但通过模块系统进行加载时,ES
    6会将文件当作独立的模块来处理。每个模块都可以导入其他模块或特定的API成员,同样也可以到处自己的API成员。

    • import可以将一个模块中的一个或多个API导入到当前作用域中,并分别绑定在一个变量上。
    • module会将整个模块的API导入并绑定到一个变量上。
    • export会将当前模块的一个标识符(变量、函数)导出为公共API。

    四)、小结:

    • 闭包虽然随处可见,但是不要滥用。使用闭包在处理速度和内存消耗方面对脚本性能具有负面影响。
    • 理解闭包的关键还是前几章讲述的词法作用域,因此不能跳过前几章!
  • 相关阅读:
    文件下载的多种方法
    WebService返回DataTable问题
    PowerDesigner设置
    C#中简单的写日志的方法
    sql server 汉字的长度
    validateRequest="false"属性及xss攻击
    TotoiseSVN的基本使用方法
    有选择性的生成一个表的插入脚本,不是选择全部数据生成
    xml2-config not found.
    Ueditor编辑旧文章,从数据库中取出要修改的内容
  • 原文地址:https://www.cnblogs.com/enmac/p/13090177.html
Copyright © 2011-2022 走看看