javascript中IIFE立即执行函数表达式来龙去脉解析

 更新时间:2025年07月01日 08:59:46   作者:前端风云志  
Ben Alman于2010年提出IIFE立即执行函数表达式,取代旧称Self-ExecutingAnonymousFunction,通过括号包裹函数声明转为表达式,实现立即执行,常见形式为()包裹,其他变种如new、void等不推荐使用,感兴趣的朋友一起看看吧

介绍

IIFE(Immediately Invoked Function Expression),中文名称:立即执行函数表达式,其实IIFE最早并不叫这个名字,而是叫做Self-Executing Anonymous Function,即自执行匿名函数。根据MDN的资料,IIFE这个说法最早由Ben Alman于2010年提出,下面我们一起来看看这个名字的来龙去脉。

2010年11月5日,Ben Alman写下来他的著名文章:Immediately-Invoked Function Expression (IIFE),标志着IIFE这个名字的诞生。

在文章中,Ben Alman称他是一个对待术语非常严谨的人,之前他多次看到Self-Executing Anonymous Function这个说法,觉得不是很恰当,于是他提出了Immediately-Invoked Function Expression这个说法。

IIFE到底是咋来的?

当我们定义一个函数或者一个函数表达式时,你得到的是一个名字,通过这个名字,你就可以调用这个函数。

下面这两段代码,第一个定义了一个普通函数,第二个定义了一个函数表达式,这两种形式,我们都可以通过标识符foo来调用它们。

// 普通函数
function foo() {
  console.log('I am a function');
}
// 函数表达式
const foo = function() {
  console.log('I am a function expression');
};

也就是说,当javascript解释器遇到全局function关键字,或者一个函数内部的function关键字时,会将其解释为一个函数声明。

然而函数声明是无法直接调用的,所以下面的写法会导致错误:

function foo() {
  console.log('I am a function'); // Uncaught SyntaxError: Unexpected token ')'
}();

我们来分析一下,上面这段代码,javascript解释器会将其解释为一个函数声明,和一个分组操作符(()), 分组操作符是用来改变运算符优先级的,里面必须有表达式才行,所以javascript解释器会报错。

那我们就给它一个表达式:

function foo() {
  console.log('I am a function'); // Uncaught SyntaxError: Unexpected token ')'
}(1);

这回代码不报错了,但是这段代码毫无意义,这个函数并没有执行,实际上这段代码与下面的代码等价:

function foo() {
  console.log('I am a function');
}
(1);

它的返回值就是1,这不是我们想要的结果,我们需要函数定义后能立即被执行,那就需要我们告诉javascript解释器,这个函数是一个表达式,而不是一个声明,因为表达式可以立即执行,但是声明不能。

而在javascript中,生成表达式最简单的方式就是用()包裹起来,于是有了下面的代码

(function foo() {
  console.log('I am a function');
});

这样函数声明就变成了一个函数表达式,但是这个表达式没有名字,我们没法调用它,我们先给它一个名字,然后通过名字调用它。

const bar = (function foo() {
  console.log('I am a function');
});
bar(); // I am a function

这样完全没有问题,但是这里的bar实在有点多余,实际上bar

(function foo() {
  console.log('I am a function');
});

是等价的,既然bar()可以调用函数,那么我们直接在函数表达式末尾加上(),也可以调用这个函数,于是就有了下面的代码,这就是IIFE的由来。

(function foo() {
  console.log('I am a function');
})();

()写在外层的括号内也一样,这种方式颇得javascript专家Douglas Crockford的青睐。我本人更喜欢第一种。

(function() {
  console.log('I am a function');
}());

IIFE的变种

由上面介绍可知,生成IIFE的精髓就是将函数声明变成函数表达式,而在javascript中,生成表达式可不止使用()包裹起来这一种方式,还有很多其他的方式可以实现。于是IIFE也就是产生了诸多变种。

这个变种利用赋值运算符=来实现,赋值运算符是将右侧表达式的值赋值给左侧变量的,所以它右侧的部分被解析成了函数表达式及其调用。

const i = function() {
  console.log('I am an IIFE');
}();

下面的表中使用逻辑运算符来生成表达式。

true & (function() {
  console.log('I am an IIFE');
}());

还有下面这些,都是利用一元运算符来生成函数表达式。

!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

最后来一个不为人知的,void运算符会对其右侧的表达是求值然后返回undefined。(void expression - 先对expression求值,然后返回undefined)。

void function() {
  console.log('I am an IIFE');
}();

还有使用new运算符来生成IIFE,这种方式比较少见,因为它会创建一个新的对象。

new function() {
  console.log('I am an IIFE');
}();

这些方式都比较偏门了,不建议使用,只是用来帮助我们理解IIFE的。

为什么Self-Executing Anonymous Function这个名字不好?

Ben Alman认为这个名字有两个问题:

Self-Executing:这个名字暗示函数会调用自己,但是实际上函数是立即被执行的,而不是调用它自身。
比如下面的几段代码都会调用自己,但是这并不是IIFE的语义。

// 递归调用自身
function foo() { foo(); 
// 使用arguments.callee调用自身
const foo = function() { arguments.callee(); };

Anonymous:这个名字暗示函数是匿名的,但实际上函数可以有名字,也可以没有名字,比如下面的例子:

// 有名字的IIFE
(function foo() {
  console.log('I am an IIFE');
})();

参考

https://web.archive.org/web/20171201033208/http://benalman.com/news/2010/11/immediately-invoked-function-expression/#iife

大家有时间可以去拜读Ben Alman的原文,大佬写的东西就是不一样,通俗易懂,是我辈楷模!

到此这篇关于javascript中IIFE(立即执行函数表达式)到底是咋来的?的文章就介绍到这了,更多相关javascript中IIFE(立即执行函数表达式)到底是咋来的?内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JS面试必备之如何实现一个精确的倒计时

    JS面试必备之如何实现一个精确的倒计时

    又到了金三银四的季节了,面试的各位同学要开始准备起来了,今天主要分享一个在面试中经常被提到的一个面试题:倒计时,希望对大家有所帮助
    2024-03-03
  • JavaScript 判断浏览器是否支持SVG的代码

    JavaScript 判断浏览器是否支持SVG的代码

    SVG(可缩放矢量图形),接下来将介绍下如何判断浏览器是否支持SVG,感兴趣的朋友可以参考下哈,希望本代码对你有所帮助
    2013-03-03
  • 原生js实现九宫格拖拽换位

    原生js实现九宫格拖拽换位

    这篇文章主要为大家详细介绍了原生js实现九宫格拖拽换位,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-01-01
  • JS HTML5拖拽上传图片预览

    JS HTML5拖拽上传图片预览

    这篇文章主要为大家详细介绍了JS HTML5拖拽上传图片预览的相关资料,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-07-07
  • javascript数组排序汇总

    javascript数组排序汇总

    本文给大家汇总了一下javascript的数组排序算法,包括冒泡排序、快速排序、插入排序、希尔排序,希望对大家熟悉javascript数组排序能够有所帮助。
    2015-07-07
  • javascript实现下雪效果【实例代码】

    javascript实现下雪效果【实例代码】

    下面小编就为大家带来一篇javascript实现下雪效果【实例代码】。小编觉得挺不错的,现在分享给大家,也给大家做个参考
    2016-05-05
  • js删除对象/数组中null、undefined、空对象及空数组方法示例

    js删除对象/数组中null、undefined、空对象及空数组方法示例

    这篇文章主要给大家介绍了关于js删除对象/数组中null、undefined、空对象及空数组的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面随着小编一起来看看吧
    2018-11-11
  • JavaScript中捕获与冒泡详解及实例

    JavaScript中捕获与冒泡详解及实例

    这篇文章主要介绍了JavaScript中捕获与阻止捕获、冒泡与阻止冒泡详解及实例的相关资料,需要的朋友可以参考下
    2017-02-02
  • javascript模拟实现计算器

    javascript模拟实现计算器

    这篇文章主要为大家详细介绍了javascript模拟实现计算器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-04-04
  • 原生js实现无缝轮播图

    原生js实现无缝轮播图

    这篇文章主要为大家详细介绍了原生js实现无缝轮播图,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01

最新评论