为何在立即执行函数表达式(IIFE)中使用`+`或`!`运算符?两种特殊形式IIFE的工作原理问询
!function(){...}()和+function(){...}()能作为立即执行函数(IIFE)? Great question! Let's clear up your confusion and break down how these IIFE variants work, step by step.
先纠正你的误解
你之前的思路有点跑偏了:这些运算符不是先把函数转换成布尔值/数值再执行,而是反过来——它们先让JavaScript把function(){...}识别为函数表达式(而非函数声明),这样我们才能立即调用它,最后才对函数的返回值做运算。
核心原理:区分函数声明 vs 函数表达式
在JavaScript中,单独写function(){/* code */}会被解析为函数声明,而函数声明是不能直接加()调用的(会触发语法错误)。要让函数能被立即调用,我们需要把它变成函数表达式——这就是标准写法(function(){})()的作用,而!、+这类一元运算符也能实现同样的效果:
一元运算符(!、+、-、~等)需要一个表达式作为操作数,所以当你在function(){...}前加这些运算符时,JavaScript会自动把它解析成函数表达式,而不是声明。这就给了我们调用它的权限。
逐个解析两种写法
1. !function(){/* code */}()
执行流程是:
- 第一步:
!强制后面的function(){...}成为函数表达式; - 第二步:
()调用这个函数,执行内部代码,得到函数的返回值(如果没有return语句,返回undefined); - 第三步:
!对返回值取反(比如!undefined得到true),但这个结果通常会被忽略——我们只关心函数内部代码的执行。
你之前以为是执行true(),其实完全不是:函数本身先被调用执行,之后才对返回值做取反操作,核心是第一步的表达式转换。
2. +function(){/* code */}()
逻辑和上面一致:
- 第一步:
+把function(){...}转为函数表达式; - 第二步:
()调用函数,执行内部代码; - 第三步:
+把函数返回值转为数值(比如undefined转成NaN,返回数字就保持原数,返回字符串会尝试转成数值),同样这个结果我们不需要,只是利用+的语法特性触发表达式解析。
为什么要用这些运算符,而不是括号?
- 更简洁:比标准的
(function(){})()少写一个括号,代码更紧凑; - 风格偏好:部分开发者觉得这类写法更顺手,或者能让代码看起来更独特;
- 多样性:除了
!和+,-、~、void也能实现同样效果,比如void function(){/* code */}()——原理完全相同,都是把函数声明转为表达式。
举个直观的例子:
直接写
function(){console.log('Hello!')}()会抛出语法错误,因为这是函数声明,不能直接调用。
但写!function(){console.log('Hello!')}()就会正常输出Hello!,同时返回true(对undefined取反的结果),而我们只需要前半部分的执行效果。
总结
!和+这类运算符的核心作用是强制函数声明转换为函数表达式,让JavaScript允许我们立即调用它。它们对返回值的类型转换只是附带效果,我们通常不需要这个结果——只是借了它们的语法特性来实现IIFE。
内容的提问来源于stack exchange,提问作者made bird

