写点什么

javascript 中 IIFE(立即执行函数表达式)到底是咋来的?

  • 2025-07-01
    福建
  • 本文字数:2145 字

    阅读完需:约 7 分钟

介绍


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://www.cnblogs.com/graphics/p/18959048

体验地址:http://www.jnpfsoft.com/?from=001YH

用户头像

还未添加个人签名 2025-04-01 加入

还未添加个人简介

评论

发布
暂无评论
javascript中IIFE(立即执行函数表达式)到底是咋来的?_JavaScript_电子尖叫食人鱼_InfoQ写作社区