美文网首页JavaScript
JS中的IIFE和闭包

JS中的IIFE和闭包

作者: 西瓜鱼仔 | 来源:发表于2019-10-08 13:52 被阅读0次

IIFE( 立即调用函数表达式)

是一个在定义时就会立即执行的JavaScript函数。

(function () {
    statements
})();

这是一个被称为自执行匿名函数的设计模式,主要包含两部分。第一部分是包围在 圆括号运算符 () 里的一个匿名函数,这个匿名函数拥有独立的词法作用域。这不仅避免了外界访问此 IIFE 中的变量,而且又不会污染全局作用域。

第二部分再一次使用 () 创建了一个立即执行函数表达式,JavaScript 引擎到此将直接执行函数。

IIFE有以下特性:
1.当函数变成立即执行的函数表达式时,表达式中的变量不能从外部访问。

(function () { 
    var name = "Barry";
})();
// 无法从外部访问变量 name
name // 抛出错误:"Uncaught ReferenceError: aName is not defined"

2.将IIFE分配给一个变量,不是存储IIFE本身,而是存储IIFE执行后返回的结果。

var result = (function () { 
    var name = "Barry"; 
    return name; 
})(); 
// IIFE 执行后返回的结果:
result; // "Barry"

闭包

我个人理解是:因为作用域的存在,外部函数调用某个函数后,其变量对象本应该被销毁,但闭包的存在使我们仍然可以从外部访问此函数的变量对象(类比理解:比如windows系统删除正在使用的文件是删除不了的,因为文件正在被使用)。

在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。
演示代码:

function show() {
      var num = 666;
      return function () {
        console.log(num);
      }
    }

    var show2 = show();   //show函数在此执行一次
    show2();

打印结果是:666

IIFE和闭包的结合使用

1)ES5没有块作用域带来的影响

首先看一段代码:

 var arr = [];
    for (var i=0;i<3;i++){
      arr[i] = function () {
        return i;
      };
    }
    console.log(arr[0]());
    console.log(arr[1]());
    console.log(arr[2]());

按照我们心理预期,结果打印应该是:0,1,2
但是最终打印结果却是:3,3,3。这是为什么呢?
我们把上述代码稍作修改:

 var arr = [];
    for (var i=0;i<3;i++){
      arr[i] = function () {
        return i;
      };
    }
    console.log(arr[0]);   //修改的地方,去掉了()
    console.log(arr[1]);   //修改的地方,去掉了()
    console.log(arr[2]);   //修改的地方,去掉了()

打印结果为:


由此可见,由于函数未实际执行,for 循环并没有把i的具体值给arr[],而是让i待命。
由于ES5没有块作用域,for 循环条件中定义的变量 i 实际上是一个全局变量,这个 i 会随着 for 的执行,不断被覆写。直到它的值变为3,当页面加载完来执行 arr[0]() 函数时,arr[0]() 中待命的 i 会找 i 的最终结果,所以最后打印出来的是3,3,3。

2)使用IIFE+闭包解决ES5没有块作用域带来的影响。

直接上代码:

  var arr = [];
    for (var i=0;i<3;i++){
      //使用IIFE
      (function (i) {
        arr[i] = function () {
          return i;
        };
      })(i);
    }
    console.log(arr[0]());
    console.log(arr[1]());
    console.log(arr[2]());

因为IIFE是立即执行,所以 i 具体值会被写进 arr[0]() 中,最后打印结果为:0,1,2

3)附加:使用更简单的ES6语法来解决

var arr = [];
    for (let i=0;i<3;i++){
      //使用IIFE
      (function (i) {
        arr[i] = function () {
          return i;
        };
      })(i);
    }
    console.log(arr[0]());
    console.log(arr[1]());
    console.log(arr[2]());

最后打印结果为:0,1,2.
这是因为ES6语法增加了块作用域,for 循环的值不会再随着循环执行不断覆写,而是每次循环都把 i 的值单独保存下来。

相关文章

  • JS中的IIFE和闭包

    IIFE( 立即调用函数表达式) 是一个在定义时就会立即执行的JavaScript函数。 这是一个被称为自执行匿名...

  • JS之闭包与IIFE

    本篇文章主要讨论了: JavaScript引擎 全局对象 闭包 循环 + 闭包 IIFE + 闭包 1.JavaS...

  • php之闭包函数(Closure)

    php闭包函数(Closure) JS闭包 js和php闭包使用和区别

  • 学习JavaScript闭包和作用域笔记

    JS JavaScript闭包和作用域 闭包 JavaScript高级程序设计中对闭包的定义:闭包是指有权访问另外...

  • JS闭包大结局(JS闭包系列3)

    在上一篇中再谈JS闭包(JS闭包系列2),我详细的介绍了JS中的变量作用域相关的概念,结合第一节关于JS闭包(JS...

  • 关于立即执行函数IIFE

    [译] JavaScript:立即执行函数表达式(IIFE) IIFE保存闭包的状态 就像当函数通过他们的名字被调...

  • JS中的IIFE(立即执行方法)

    IIFE:immediately-invoked function expression 通常函数的闭包时这样写的...

  • Day4 闭包

    闭包允许函数访问定义时的词法作用域回调函数基本上都是闭包模块利用闭包隔离变量,暴露公共API(也会伴随IIFE立即...

  • js循环引用引起的内存泄漏示例

    Js中存在和OC同等意义的闭包(block& closure)闭包可看作匿名函数,例如: 函数中 给element...

  • 简单的聊一下闭包

    js中的闭包 闭包是学习js中永远也绕不过去的一个坎,那么,今天我们就去一段简单的代码开始聊一聊闭包 什么是闭包 ...

网友评论

    本文标题:JS中的IIFE和闭包

    本文链接:https://www.haomeiwen.com/subject/xcsbpctx.html