js中自运行的匿名函数
loyalvi Lv7

JS中自运行的匿名函数

JS中自运行的匿名函数

在JS中可以使用匿名函数,原理非常简单。在JS中函数其实也是一种对象,在底层只要用一块内存将其保存下来即可。 在调用时只需要找到这块内存,然后创建好执行环境(包括参数数组、变量数纽等内容)就可以执行了。 所以有两个关键方面:

  • 将函数对象保存到一块内存中
  • 找到这块内存
    通常使用函数名来查找这块内存的地址,不过函数名只是查找这块内存的一个工具,最主要的目的其实是找到这块内存,也就是说,即使没有函数名也可以,只要能找到这块内存就行。因此可以使用匿名函数,其用法如下。
    首先使用 function 关键字定义一个函数,然后将其使用小括号括起来(这只是语法的要求,否则后面的执行语句无法被引擎正确识别,这样就将函数定义好了,引擎会为其分配一块内存来保存。 然后直接在后面加个小括号,并将参数放入其中,这样引擎就知道要使用这块内存所保存的函数来执行了。因为对于JS来说,在函数后面加小括号是调用函数的意思,这是JS的语法规则(如果是我们来设计,当然也可以设计为见到“调用XXX ”的字符串执行函数)。这时既有保存函数的内存也有内存的地址,这样就可以 执行了。 例如,上面的例子中首先定义了一个函数,然后使用小括号将其扩起来,后面又加了一个表示执行的小括号,并将参数 81 放入其中,这样就可以执行了。
1
2
3
4
5
6
7
var log = (function () { 
console.log("111");
return function(param) {
console.log(param);
};
})();
log("222");

这里也创建了一个自运行的匿名函数,不过其返回值仍然是一个匿名函数,也就是说函数自运行后返回的结果仍然是一个函数。把返回的函数赋值给log变量,就可以使用 log 变量来调用返回的函数了(注意与前面所介绍的函数表达式创建函数的区别)。这里其实包含两块保存函数的内存,自运行的匿名函数本身有一块内存来保存,当碰到后面表示执行的小括号后就会自动执行,另外还有一块内存来保存所返回的函数,而返回的值其实是这块内存的地址,这样 log 变量指向了这块保存函数的内存,因此也可以使用 log 来调用此函数 。 虽然 JS 表面看起来有很多复杂的东西,但只要理解了其本质(特别是内存模型)后就很简单了。

匿名函数

匿名函数(Anonymous Function)是一种没有指定名称的函数。在 JavaScript 中,匿名函数通常通过函数表达式来创建。以下是一些关于匿名函数的详细信息和示例:

创建匿名函数

  • 函数表达式
    • 匿名函数通常通过函数表达式来定义,即把函数赋值给一个变量。
    1
    2
    3
    4
    const myFunction = function() {
    console.log('Hello, World!');
    };
    myFunction(); // 调用匿名函数
  • 立即调用函数表达式(IIFE)
    • 匿名函数可以立即执行,通常用于创建一个独立的作用域,避免变量污染全局作用域。
    1
    2
    3
    (function() {
    console.log('This is an IIFE');
    })();

使用场景

  • 事件处理
    • 匿名函数常用于事件处理中,因为事件处理函数通常不需要在其他地方重复使用。
    1
    2
    3
    document.getElementById('myButton').addEventListener('click', function() {
    console.log('Button clicked!');
    });
  • 回调函数
    • 在异步操作中,匿名函数常用作回调函数,因为回调函数通常只在特定事件发生时执行一次。
    1
    2
    3
    setTimeout(function() {
    console.log('This message is delayed by 2 seconds');
    }, 2000);
  • 局部作用域
    • 使用立即调用函数表达式(IIFE)可以创建一个局部作用域,用于封装代码和变量。
    1
    2
    3
    4
    5
    (function() {
    const secret = 'hidden';
    console.log(secret);
    })();
    // secret 在外部是不可访问的

优点

  • 简洁:不需要为函数命名,代码更简洁。
  • 局部作用域:通过 IIFE,可以创建局部作用域,避免变量污染全局作用域。
  • 灵活性:可以在需要时即时定义和使用函数。

缺点

  • 调试困难:由于没有函数名,调试时可能较难识别函数来源。
  • 重复使用:如果需要在多个地方使用相同的逻辑,使用匿名函数会导致代码重复。

箭头函数与匿名函数

  • 箭头函数
    • 箭头函数是 ES6 引入的一种更简洁的函数语法,也可以用于创建匿名函数。
    1
    2
    3
    4
    const myArrowFunction = () => {
    console.log('Hello, World!');
    };
    myArrowFunction(); // 调用箭头函数
  • 区别
    • 箭头函数不绑定自己的 this,而是捕获其所在上下文的 this 值。
    • 箭头函数不能用作构造函数,也没有 arguments 对象和 super 关键字等.
      通过合理使用匿名函数,可以在 JavaScript 中实现更灵活和简洁的代码结构,特别是在事件处理和异步编程中.

IIFE

IIFE(Immediately Invoked Function Expression),即立即执行函数表达式,是一种在JavaScript中定义后立即执行的函数。其基本语法如下:

1
2
3
(function() {
// 函数体
})();

也可以传递参数给IIFE,例如:

1
2
3
(function(name) {
console.log("Hello, " + name + "!");
})("World");

使用场景

  • 创建局部作用域:在JavaScript中,变量的作用域决定了它们的可访问性。通常情况下,函数内部的变量是局部的,但如果我们在全局作用域中定义变量,它们就会变得全局可用。使用IIFE,可以创建一个局部作用域,从而保持变量的私有性。例如:
    1
    2
    3
    4
    5
    (function() {
    var localVar = "I'm local";
    console.log(localVar); // 输出: I'm local
    })();
    console.log(localVar); // ReferenceError: localVar is not defined
  • 模块化开发:随着JavaScript的不断发展,模块化开发的概念日益受到重视。IIFE可以作为模块的基础结构,允许定义私有变量和公开方法。例如:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    var myModule = (function() {
    var privateVar = "private";
    function privateMethod() {
    console.log(privateVar);
    }
    return {
    publicMethod: function() {
    privateMethod();
    }
    };
    })();
    myModule.publicMethod(); // 输出: private
  • 处理异步代码:IIFE也经常用于处理异步代码,如回调函数和定时器。通过将异步逻辑封装在IIFE中,可以确保代码的正确执行顺序,并避免潜在的作用域问题。

优点

  • 封装性:IIFE允许将变量封装在函数内部,避免了全局命名冲突。
  • 模块化:可以创建模块化的代码架构,有助于代码的组织和管理。
  • 立即执行:代码可以在定义后立即执行,适合于一些初始化的任务。

缺点

  • 可读性:对于初学者来说,IIFE的语法可能会导致一些理解上的困难。
  • 调试:由于函数的命名通常是匿名的,调试时可能不利于跟踪函数的调用。
由 Hexo 驱动 & 主题 Keep
访客数 访问量