一 什么是立即执行函数表达式

立即执行函数表达式,其实也可以叫初始化函数表达式,英文名:IIFE,immediately-inovked-function expression。立即执行函数表达式就是在定义的时候就立即执行。

二 立即执行函数表达式的写法

1)写法一

 (function (a) {
console.log('The result is ' + a);
})(5);
// The result is 5

2)写法二

 (function (a) {
console.log('The result is ' + a);
}(5));
// The result is 5

三 立即执行函数表达式的特点

1)作用域隔离,避免污染全局的命名空间

通过定义一个匿名函数,创建了一个新的函数作用域,相当于创建了一个“私有”的命名空间,该命名空间的变量和方法,不会破坏污染全局的命名空间。如果想传给外部变量或者方法,通过给window上添加对应属性即可。

例如:Jquery插件就是将window传入,然后给window上添加了$属性。

2)执行完立即销毁

执行完后,内部的局部变量和整个函数会被销毁释放掉。

 (function add(a, b) {
console.log('The result is ' + (a + b));
return a + b;
}(5, 3)); add(4, 6); // The result is 8
// Uncaught ReferenceError: add is not defined

3)立即执行函数表达式不需要带函数名

如果带了函数名,则被自动忽略。

四 立即执行函数表达式的错误写法

下边会针对一些立即执行函数表达式的错误写法,深入说明其原因。

要很好的理解下边错误写法的原因,首先要了解:JavaScript中函数的定义方法;JavaScript中表达式。

1)错误写法一

下边的错误写法的原因:浏览器解析器遇到function开头的语句,认为这是一个函数定义,但发现该函数没有函数名,导致报错。

 function () {
console.log('The result is 1');
}(); // Uncaught SyntaxError: Unexpected token (

说明:为什么给上边示例代码添加一个圆括号,就可以执行并且不报错了?

这是因为添加圆括号后,就变成表达式。

我们都知道定义函数有两种方式:

 // 函数声明:使用function声明函数,并指定函数名
function add() {
console.log('The result is 1');
} // 函数表达式:使用function声明函数,但未指定函数名,将匿名函数赋予一个变量
var add = function() {
console.log('The result is 1');
};

因此立即执行函数表达式,就类似于给函数表达式方式定义的函数,只是在函数定义完添加了圆括号让该函数立即执行了。

根本的原因还是将一个函数定义,变成了一个表达式。这也是为什么叫立即执行函数表达式的原因。

让一个匿名函数变成一个表达式的方法很多:

 !function(){}();
+function(){}();
-function(){}();
~function(){}();
new function(){ /* code */ }
new function(){ /* code */ }() // 只有传递参数时,才需要最后那个圆括号。
……

2)错误写法二

 function add() {
console.log('The result is ' + a);
}(); // Uncaught SyntaxError: Unexpected token )

上边代码会被浏览器解析为如下样子:

 function add() {
console.log('The result is ' + a);
};
();

第一个分号前是一个完整的函数定义,没有问题;而第二个分号前的(),出现了语法报错。

注意:当我们给后边的那个圆括号中添加一个表达式后,就不会报错了。但注意add函数依然不会执行。

 function add() {
console.log('The result is 1');
}(2); // 上边等价于下边代码:一部分是函数声明,一部分是执行表达式。因此函数不会执行。
function add() {
console.log('The result is 1');
};
(2);

3)错误写法三

当有多个立即执行函数表达式时,一定要带分号:

 (function () {
console.log('this is IIFE 1');
}())
(function () {
console.log('this is IIFE 1');
}()) // VM80:4 Uncaught TypeError: (intermediate value)(...) is not a function

说明:不带分号会导致JavaScript执行器认为后边括号内容是前边括号内容的参数,而前边括号最终执行结果并不是一个函数。而下边代码就不会报错:

 (function () {
console.log('this is IIFE 1');
return function(a) {
console.log('this is IIFE 1 return');
}
}())
(function () {
console.log('this is IIFE 2');
}()) // this is IIFE 1
// this is IIFE 2
// this is IIFE 1 return

五 立即执行函数组成的闭包保存状态

 // 这个代码是错误的,因为变量i从来就没背locked住
// 相反,当循环执行以后,我们在点击的时候i才获得数值
// 因为这个时候i操真正获得值
// 所以说无论点击那个连接,最终显示的都是I am link #10(如果有10个a元素的话) var elems = document.getElementsByTagName('a'); for (var i = 0; i < elems.length; i++) { elems[i].addEventListener('click', function (e) {
e.preventDefault();
alert('I am link #' + i);
}, 'false'); } // 这个是可以用的,因为他在自执行函数表达式闭包内部
// i的值作为locked的索引存在,在循环执行结束以后,尽管最后i的值变成了a元素总数(例如10)
// 但闭包内部的lockedInIndex值是没有改变,因为他已经执行完毕了
// 所以当点击连接的时候,结果是正确的 var elems = document.getElementsByTagName('a'); for (var i = 0; i < elems.length; i++) { (function (lockedInIndex) { elems[i].addEventListener('click', function (e) {
e.preventDefault();
alert('I am link #' + lockedInIndex);
}, 'false'); })(i); } // 你也可以像下面这样应用,在处理函数那里使用自执行函数表达式
// 而不是在addEventListener外部
// 但是相对来说,上面的代码更具可读性 var elems = document.getElementsByTagName('a'); for (var i = 0; i < elems.length; i++) { elems[i].addEventListener('click', (function (lockedInIndex) {
return function (e) {
e.preventDefault();
alert('I am link #' + lockedInIndex);
};
})(i), 'false'); }

六 参考资料&内容来源

博客园:https://www.cnblogs.com/tomxu/archive/2011/12/31/2289423.html

SF:https://segmentfault.com/a/1190000003902899

百度:https://baijiahao.baidu.com/s?id=1627496475450434415&wfr=spider&for=pc

博客园:https://www.cnblogs.com/yanzp/p/6371292.html

【JavaScript专题】--- 立即执行函数表达式的更多相关文章

  1. (译)详解javascript立即执行函数表达式(IIFE)

    写在前面 这是一篇译文,原文:Immediately-Invoked Function Expression (IIFE) 原文是一篇很经典的讲解IIFE的文章,很适合收藏.本文虽然是译文,但是直译的 ...

  2. [转]Javascript中的自执行函数表达式

    [转]Javascript中的自执行函数表达式 本文转载自:http://www.ghugo.com/javascript-auto-run-function/ 以下是正文: Posted on 20 ...

  3. 详解javascript立即执行函数表达式(IIFE)

    立即执行函数,就是在定义函数的时候直接执行,这里不是申明函数而是一个函数表达式 1.问题 在javascript中,每一个函数在被调用的时候都会创建一个执行上下文,在函数内部定义的变量和函数只能在该函 ...

  4. 【JavaScript】浅析IIFE(立即执行函数表达式)的作用

    什么是IIFE IIFE就是立即执行函数表达式(Immediately-Invoked Function Expression) 为什么需要IIFE 应用IIFE有两个比较经典的使用场景, 第一就是在 ...

  5. 立即执行函数表达式(IIFE)

    原文地址:benalman.com/news/2010/11/immediately-invoked-function-expression/ 译者:nzbin 也许你还没有注意到,我是一个对术语比较 ...

  6. javascript立即调用的函数表达式N种写法(第二篇)

    原文:javascript立即调用的函数表达式N种写法(第二篇) 上一篇博客我谈到将函数声明转换为函数表达式最常见的一种写法是:通过括号()将匿名函数声明转换为函数表达式即(function(){}) ...

  7. JS立即执行函数表达式(IIFE)

    原文为 http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife ----------------- ...

  8. 理解JavaScript的立即调用函数表达式(IIFE)

    首先这是js的一种函数调用写法,叫立即执行函数表达式(IIFE,即immediately-invoked function expression).顾名思义IIFE可以让你的函数立即得到执行(废话). ...

  9. IIFE(立即执行函数表达式)

    我们经常会看到这样的写法: ;(fuction () { // do something })() 这就是一个简单的IIFE(立即执行函数表达式,immediately-invoked functio ...

随机推荐

  1. mysql 修改字符集为utf8mb4

    一般情况下,我们会设置MySQL默认的字符编码为utf8,但是近些年来,emoji表情的火爆使用,给数据库带来了意外的错误,就是emoji的字符集已经超出了utf8的编码范畴

  2. 倍福TwinCAT(贝福Beckhoff)基础教程4.2 TwinCAT如何读写CSV文件

    本程序只是在官方范例程序上稍作修改,在官方原有的范例中,演示了多种模式的读写(可以认为CSV文件是比TXT文件需要更多数据量的时候使用,比如记录一个小型的数据库集合)   但是写的比较混乱,甚至没有H ...

  3. SQL 关键字 'USER' 附近有语法错误怎么办

    如下图所示,我想要访问我的Database1.mdf的user这张表,提示如下错误   user在SQL Server中是系统保留字,将user修改为[user]就可以了.但是直接在VS中是无法修改的 ...

  4. 创建你的第一个ionic+cordova应用(1)

    前面我们安装了前端的神器webstorm11,体验到了强大的开发体验,接着我们来安装ionic 必备: Node.js (npm安装工具) 百度下载 官网下载  注:如果官网新版不能安装请用百度下载0 ...

  5. windows新建或者重命名文件及目录必须手动刷新才干显示出来问题解决方法

     首先推断注冊表中HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Update\UpdateMode值是否为0,该值若为1表示手工刷新, 该 ...

  6. awk、sed、cut、grep

    二.sed [可以理解为 行在线编辑工具] 作用:sed 是一种在线编辑器,它一次处理一行内容.处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命 ...

  7. ROS当中添加第三方库

      下文以serial 库为依据讲解第三方库在ROS下面的配置. 参考文献:http://blog.csdn.net/u011853479/article/details/51263590 ros中使 ...

  8. c# 冒号 :

    1.表示继承关系 class classA:classB 2.继承构造, 调用自己这个类的某个构造函数,因为有的类构造函数很多参数,而有的参数又不是必须填写,或者可以提供一些默认值,就跟重载是一样的道 ...

  9. js项目第一课:获取节点的方法有三个

    第一种方法: demo.html代码如下:<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &qu ...

  10. Dual Camera Info

    一个摄像头解决不了的问题,那就用两个:对于双摄你需要了解这些 http://www.chengshiluntan.com/wg/a/20160715/6ca0343f59789235c9419887f ...