js 立即执行函数表达式(Immediately Invoked Function Expression,简称 IIFE):(function () {})();

1、解释

(function () {
  // 函数体
})();

可以分成两部分理解:

  1. (function () { ... })

    • 这是一个函数表达式,被包裹在括号 () 中。
    • JavaScript 引擎会把它当作一个表达式(而不是函数声明),因此可以立即调用
  2. ()(最后的这对括号)

    • 表示立刻调用前面定义的这个函数。
    • 就像你写 myFunction() 一样,这里是“定义完就马上执行”。

2、作用

1. 创建私有作用域(避免污染全局变量)

在 IIFE 内部定义的变量、函数,不会暴露到全局作用域,防止命名冲突。

(function () {
  var secret = '123456'; // 这个变量只在 IIFE 内部可见
  console.log(secret);   // 可以访问
})();

console.log(secret); // ❌ 报错:secret is not defined

2. 避免命名冲突

var count = 10;

(function () {
    var count = 20;  // 独立的局部变量
    console.log(count); // 20
})();

console.log(count); // 10

3. 模块化封装(早期 JS 模块模式)

在 ES6 模块(import/export)普及之前,IIFE 是实现“模块”的主要方式。

var myModule = (function () {
  var privateVar = 'hidden';

  return {
    publicMethod: function () {
      console.log(privateVar);
    }
  };
})();

myModule.publicMethod(); // 输出 "hidden"

4. 避免变量提升(hoisting)带来的问题

由于 IIFE 创建了新作用域,里面的 varfunction 不会影响外部。

对比:不用 IIFE 的风险

// ❌ 危险:所有变量都挂到全局
var deviceState = false;
var options = {};
function init() { ... }

// 如果其他脚本也用了 deviceState,就会冲突!

而用 IIFE 后:

// ✅ 安全:完全隔离
(function () {
  var deviceState = false;
  var options = {};
  function init() { ... }
})();

现代替代方案(ES6+)

现在更推荐使用 ES6 模块:

// sdk.js
const deviceState = false;
export function readCard() { ... }

// main.js
import { readCard } from './sdk.js';

但 IIFE 在不支持模块的环境(如老项目、浏览器直接引入脚本)中仍然非常有用。

3、暴露方法给外部调用

1. 返回值方式(最常用)

// 返回一个对象,包含公开的方法
var myModule = (function () {
    var privateVar = "我是私有的";
    
    function privateMethod() {
        return privateVar;
    }
    
    function publicMethod1() {
        return "公开方法1: " + privateMethod();
    }
    
    function publicMethod2() {
        return "公开方法2";
    }
    
    // 返回要公开的方法
    return {
        method1: publicMethod1,
        method2: publicMethod2,
        // 也可以直接暴露值
        version: "1.0.0"
    };
})();

// 外部调用
console.log(myModule.method1()); // "公开方法1: 我是私有的"
console.log(myModule.method2()); // "公开方法2"
console.log(myModule.version);   // "1.0.0"

2. 全局变量方式

(function (window) {
    var privateVar = "私有数据";
    
    function privateMethod() {
        return privateVar;
    }
    
    // 挂载到全局对象
    window.myModule = {
        publicMethod: function () {
            return "使用私有数据: " + privateMethod();
        },
        anotherMethod: function () {
            return "另一个方法";
        }
    };
})(window || global); // 兼容Node.js环境

// 外部调用
console.log(myModule.publicMethod()); // "使用私有数据: 私有数据"

3. 参数注入方式(如jQuery插件)

(function ($, exports) {
    var privateData = 100;
    
    function calculate(x) {
        return privateData + x;
    }
    
    // 注入到传入的对象中
    exports.calc = calculate;
    exports.name = "计算模块";
})(jQuery, window.myPlugin = window.myPlugin || {});

// 外部调用
console.log(myPlugin.calc(50)); // 150
console.log(myPlugin.name);     // "计算模块"

4. 模块模式变体

揭示模块模式(Revealing Module Pattern)

var counterModule = (function () {
    var count = 0;
    
    function increment() {
        count++;
        return count;
    }
    
    function decrement() {
        count--;
        return count;
    }
    
    function getCount() {
        return count;
    }
    
    // 明确暴露哪些方法
    return {
        add: increment,
        subtract: decrement,
        getCurrent: getCount
        // 注意:count变量本身没有被暴露
    };
})();

// 使用
counterModule.add();      // 1
counterModule.add();      // 2
console.log(counterModule.getCurrent()); // 2

5. 支持多实例的模式

var CreateCalculator = (function () {
    // 私有静态变量(所有实例共享)
    var instanceCount = 0;
    
    function Calculator(initialValue) {
        // 私有实例变量
        var value = initialValue || 0;
        
        // 公有方法
        this.add = function (x) {
            value += x;
            return this;
        };
        
        this.getValue = function () {
            return value;
        };
    }
    
    // 静态方法
    Calculator.getInstanceCount = function () {
        return instanceCount;
    };
    
    // 工厂方法
    return function (initialValue) {
        instanceCount++;
        return new Calculator(initialValue);
    };
})();

// 创建多个实例
var calc1 = CreateCalculator(10);
var calc2 = CreateCalculator(20);

calc1.add(5);
console.log(calc1.getValue()); // 15
console.log(calc2.getValue()); // 20

实际应用示例

// 创建一个简单的工具库
var Utils = (function () {
    // 私有辅助函数
    function formatDate(date) {
        return date.toISOString().split('T')[0];
    }
    
    function validateEmail(email) {
        return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
    }
    
    // 公开的API
    return {
        // 日期处理
        getCurrentDate: function () {
            return formatDate(new Date());
        },
        
        // 字符串处理
        truncate: function (str, length) {
            return str.length > length ? str.substr(0, length) + '...' : str;
        },
        
        // 验证
        isEmail: validateEmail,
        
        // 工具方法
        debounce: function (fn, delay) {
            let timer;
            return function (...args) {
                clearTimeout(timer);
                timer = setTimeout(() => fn.apply(this, args), delay);
            };
        }
    };
})();

// 使用
console.log(Utils.getCurrentDate());
console.log(Utils.isEmail("test@example.com"));
console.log(Utils.truncate("这是一个很长的字符串", 5));

关键点:

  1. 返回值方式最常用,通过return暴露需要公开的方法

  2. 揭示模块模式更清晰,明确区分内部实现和公开接口

  3. 可以暴露方法、属性、构造函数等

  4. 私有变量和函数不会被外部直接访问

 

总结

写法名称作用
(function () {})(); IIFE(立即执行函数) 创建私有作用域,封装逻辑,避免全局污染

 

 

 

posted @ 2025-12-08 15:22  ziff123  阅读(11)  评论(0)    收藏  举报