Pixiv - KiraraShss
1067 字
5 分钟
立即执行函数
欢迎来到我的博客!
使用 Markdown 格式编写。
今天学到了什么
- 立即执行函数的优点
立即执行函数的优点在哪里?防止变量污染吗?那普通的函数不也能防止变量污染吗?
立即执行函数(IIFE, Immediately Invoked Function Expression)确实主要用于防止变量污染。
你问得非常好:“普通的函数不也能防止变量污染吗?” 答案是:是的,普通函数内部的变量也是局部的,也能防止内部变量不仅污染全局。
但 IIFE 相比普通函数,有一个极其关键的区别:
核心区别:函数名本身的污染
-
普通函数: 虽然函数内部的变量是安全的,但你为了执行这个代码,通常需要给函数起一个名字(函数声明),或者把函数赋值给一个变量。 这个“函数名”本身,就成了全局作用域中的一个变量,这就是一种污染。
// 方案 1:普通函数function init() {var age = 18; // age 确实没污染全局console.log('初始化');}init(); // 必须调用它// 问题来了:'init' 这个名字现在也是全局变量了。// 如果引入了第三方库,或者别人也写了个函数叫 init,就会冲突覆盖。 -
立即执行函数 (IIFE): 它通常是匿名的(没有名字),并且定义完马上就执行。 它不仅内部变量不污染全局,连“函数名”都不需要,彻底做到了“零污染”。
// 方案 2:IIFE(function() {var age = 18; // age 没污染console.log('初始化');})();// 完美:执行完了就销毁,全局作用域里干干净净,没有留下任何痕迹(连函数名都没有)。
总结 IIFE 的优点
- 创建独立的作用域:避免变量命名冲突(尤其是在使用
var的旧代码或需要封装库时)。 - 避免命名全局函数:不需要为了执行一段代码而专门起一个函数名,占着茅坑不拉屎。
- 内存回收:执行完毕后,如果没有引用指向它,内部变量可以立即被垃圾回收(闭包除外)。
补充:现代开发的变化 (ES6+)
你正在学习 JavaScript 基础,可能已经学到了 let 和 const。
在 ES6 之后,由于有了 块级作用域 (Block Scope),IIFE 的使用场景变少了。
// 现代写法 (ES6){ let age = 18; // 只要在一个花括号里,用 let/const 定义的变量就出不去 console.log('初始化');}// 同样做到了不污染全局,而且写法更简单,不再需要写 (function(){...})() 了。但在阅读旧代码、编写某些特定模式的插件或处理闭包时,IIFE 依然非常重要。
立即执行函数可以添加函数名
这句话是正确的,但有一个非常关键的细节需要注意:
立即执行函数(IIFE)确实可以加上函数名,但是这个名字只在函数内部有效,在外部是看不见的(不会污染全局)。
1. 代码演示
看下面这个例子,虽然给它起了名字叫 myFunc,但外面根本找不到它:
(function myFunc() { var num = 10; console.log('内部访问函数名:', myFunc); // ✅ 这里能打印出函数本身 console.log('执行完毕');})();
// ❌ 在外面访问会报错!// Uncaught ReferenceError: myFunc is not definedconsole.log(typeof myFunc); // 结果是 "undefined"(或者直接报错)2. 为什么既然外面看不见,还要给它起名字?
虽然外面用不了,但给 IIFE 起名有两个主要好处:
- 方便调试 (Debug):
如果这个函数报错了,在浏览器的控制台报错信息里,会明确显示是
myFunc出错了,而不是显示anonymous(匿名函数),让你更容易找到是哪段代码出的问题。 - 内部递归: 如果函数内部需要调用自己(递归),就可以直接使用这个名字。
总结
- 普通函数
function abc(){}:名字abc会在全局,会污染全局。 - 带名字的 IIFE
(function abc(){})():名字abc只能在自己肚子里用,不会污染全局。
所以,这句话完全没毛病,它是 IIFE 的一个高级用法。
赞助支持
如果这篇文章对你有帮助,欢迎赞助支持!
最后更新于 2026-01-30,距今已过 49 天
部分内容可能已过时