闭包与自执行函数 区别

JavaScript:闭包与自执行函数详解
本文探讨了JavaScript中的函数调用、闭包和自执行函数的概念。错误示例解释了函数声明与匿名函数表达式的差异。自执行函数在解析时作为一个表达式被执行,而闭包则允许内部函数访问外部作用域的变量,有效防止全局变量污染,并能长期保存变量状态。闭包还可用于传递参数,结合事件处理,通过匿名函数创建闭包。

函数调用

函数声明与调用
我们可以通过如下定义函数,使用fun()来调用

  fun();  // 调用函数    函数定义可以在下面
  function fun() {
      console.log(3);
  }

也可以用var来定义,此时应先声明后使用

  var fn = function() {
        console.log(4);
    }
  fn();   // 调用函数  必须先声明后使用

匿名函数

(function(x, y){ 
  alert(x + y); 
})(2, 3);

这里创建了一个匿名函数(在第一个括号内),第二个括号(2, 3)用于调用该匿名函数,并传入参数。括号是表达式,是表达式就有返回值,所以可以在后面加一对括号让它们执行.

错误1

function(){ /* code */ }(); // SyntaxError: Unexpected token (

在js解析时,当遇到function关键字时,会默认把它当做是一个函数声明,而不是函数表达式,函数声明需要一个函数名,而上面的代码中函数没有函数名。(以上代码,也正是在执行到第一个左括号(时报错,因为(前理论上是应该有个函数名的。)

错误2

function foo(){ /* code */ }(); // SyntaxError: Unexpected token )

相当于先声明了一个叫foo的函数,之后进行()内的表达式运算,但是()(分组操作符)内的表达式不能为空,所以报错。(以上代码,也就是执行到右括号时,发现表达式为空,所以报错)。
(function {// code})是表达式, function {// code}是函数声明

立即执行函数

(function(){ /* code */ })();

当js执行到(function {// code})();时, 由于(function {// code})是表达式, js会去对它求解得到返回值, 由于返回值是一 个函数, 故而遇到();时, 便会被执行。也可以表示为如下形式

var i = function(){ return 10; }();

闭包

变量的作用域分全局变量和局部变量,局部变量仅在函数内部使用
闭包的核心就是内部函数可以引用外部函数的参数和变量,通过返回函数来扩大函数的作用域,如下定义outFun函数,在里面定义了inFun函数,inFun可以调用outFun中定义的num变量,return inFun返回了内部函数体,

    function outFun() {
        var num = 10;
        function inFun() {
            console.log(num);   // 非常正常的写法
        }
        return inFun;   // 返回的是 inFun函数体  核心
    }

使用时,通过var demo = outFun();调用outFun函数返回inFun的函数体,相当于这句话 var demo = function inFun() {console.log(num); }在通过demo();调用,此时访问到了内部的num变量。
闭包可以让一个变量长期驻扎在内存中,避免全局变量的污染

var res = (function() {
     var count = 29;
     return function add() {
         count++;
         console.log(count);
     }
 })();
 res(); //30
 res(); //31

闭包传递参数
定义函数如下,定义obj变量时,传入参数,当obj()调用时,输出传入的参数。

    function Fun(x) {
        return function() {
            console.log(x);
        }
    }
    var obj = Fun(4);
    // 相当于  obj = function() {console.log(4)}
    obj();  //执行 console.log(4)

定义函数如下,定义obj时传入初始x值,obj();执行时,y参数为空,输出NaN,obj(2);执行时,输出6

    function Fun(x) {
        return function(y) {
            console.log(x+y);
        }
    }
    var obj = Fun(4);
    // 相当于  obj = function(y) {console.log(4+y)}
    obj();    //NaN
    obj(2);    //6

事件传递参数
我们将onclick事件绑定到函数体,调用move函数

    btn1.onclick = function() {
        move(5);
    }
    btn2.onclick = function() {
        move(-5);
    }
    function move(speed) {
        box.style.left = box.offsetLeft + speed + "px";
    }

通过闭包可以直接返回函数体并传递参数

    function move(speed) {
        return function() {
            box.style.left = box.offsetLeft + speed + "px";
        }
    }
    btn1.onclick = move(5);
    btn2.onclick = move(-5);

匿名函数创建闭包

var oEvent = {}; 
(function(){ 
  var addEvent = function(){ /*代码的实现*/ }; 
  function removeEvent(){} 
 
  oEvent.addEvent = addEvent; 
  oEvent.removeEvent = removeEvent; 
})();

 

### 闭包自调用函数的概念 #### 闭包 在 JavaScript 中,闭包是指一个函数能够记住并访问它的词法作用域,即使这个函数在其词法作用域之外执行。这意味着闭包可以捕获并保存其外部环境的状态[^1]。 ```javascript function createCounter() { let count = 0; return function () { count += 1; return count; } } const counter = createCounter(); console.log(counter()); // 输出: 1 console.log(counter()); // 输出: 2 ``` 这段代码展示了如何通过闭包来创建计数器。每次调用 `counter` 函数时,它都会增加并返回之前定义的 `count` 变量的值。这体现了闭包的一个重要特性:它可以保持对外部变量的引用,从而实现数据封装持久化存储[^3]。 #### 自调用函数(立即执行函数表达式) 自调用函数是一种特殊的匿名函数形式,会在被解释的同时立刻被执行。这种模式通常用于创建独立的作用域链,防止全局污染,并且可以在不暴露任何内部逻辑的情况下完成特定任务[^4]。 ```javascript (function immediateFunction() { console.log('这是来自自调用函数的消息'); })(); // 或者更简洁的形式: (() => { console.log('箭头函数版本'); })(); ``` 这两种方式都实现了相同的效果—即刻运行一段代码而不影响外界环境。值得注意的是,由于这些函数是在定义之后马上就被调用了,因此无法再重复使用它们;如果需要多次调用,则应该考虑将其赋给某个变量作为常规命名或匿名函数处理。 ### 应用场景对比 对于 **闭包** 来说: - 实现模块化的编程风格; - 构建工厂方法生成具有不同状态的对象实例; - 维护私有的成员属性服务端口连接等长期存在的资源管理操作[^2]。 而对于 **自调用函数** 而言: - 隐藏不必要的细节以减少潜在冲突的风险; - 初始化某些配置项或者启动应用程序的核心部分; - 执行一次性设置工作比如加载脚本文件、初始化插件等功能。 ### 总结 虽然两者都是基于函数的基础之上构建而成的技术手段,但是各自有着不同的侧重点以及适用范围。理解这两者的差异不仅有助于提高编码效率,还能让开发者写出结构清晰、易于维护的应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值