JavaScript闭包

1. 引言

如果您了解JavaScript函数和模块的概念,学习闭包对您来说应该不是一个大问题。如果你刚刚接触JavaScript,没有了解过这两个概念,那也没问题。闭包属于高级JavaScript概念的类别,但相信我,如果你知道和了解内部函数的工作原理,理解闭包将是小菜一碟。

2.内部函数

内部函数从根本上说是“函数内的函数”。 JavaScript支持嵌套函数,这意味着您可以在函数内创建一个或多个函数。内部函数可能再次包含内部函数,这种嵌套可以更深入。让我们看一个简单的例子。

function innerOuterDemo(){
   console.log("The outer function");

   function innerFunction(){
      console.log("The inner function");
   }
   return innerFunction;
}

函数innerOuterDemo包含一个名为innerFunction的内部函数,它将“内部函数”写入控制台。 对innerOuterDemo的调用将会将“外部函数”写入控制台并返回函数innerFunction。

var doSomething = innerOuterDemo(); // Logs "The outer function" and returns innerFunction
doSomething(); // Logs "The inner function"

十分简单且直截了当。但是请记住,一旦函数完成执行并返回,它就不再起作用了。 这表示当innerOuterDemo被执行并返回innerFunction时,innerOuterDemo不再在作用范围内。

现在我们已经介绍了函数嵌套和作用范围的基础知识,先让我们跳出闭包。 思考下面的例子:

function foodAndMore(){
   var myFood = "Pizza and Pasta";

   function getMyFood(){
      return myFood;
   }

   return getMyFood;
}

var foodILove = foodAndMore();
console.log("I love " + foodILove());

和第一个例子非常类似,除了变量myFood。 变量myFood属于外部函数foodAndMore,但却在内部函数getMyFood内部作为return语句的部分来使用。 调用foodAndMore函数将返回的getMyFood函数分配给变量foodILove。 当您运行上述代码段时,控制台将会出现“我喜欢披萨和面食“。

这里有什么特别之处呢? 之前我说过,当函数完成执行时它就不再起作用了? 但是如果是这样,在执行完函数foodAndMore并返回时,不应该包含变量myFood。但是您在控制台中看到“我喜欢披萨和面食”的输出,那肯定不是这样的,那到底是什么样的呢?这就要看下面的介绍了。

3.闭包

闭包是内部函数访问外部函数变量的一个桥梁。 换句话说,闭包是一个可以访问外部函数的变量内部函数。 回过头来,让我们继续看上一个关于食物的例子。 正如我们已经观察到的,内部函数getMyFood可以访问外部函数的变量myFood,即使外部函数已经执行完毕。 所以函数getMyFood和变量myFood的组合就是一个闭包的例子。 我们可以随时通过引用变量(例如foodILove)来调用getMyFood函数并获取“Pizza and Pasta”的myFood变量的值。

在JavaScript中,内部函数不仅可以访问外部函数的变量,还可以访问它们的参数。 下一个例子将证明这一点。

function getMultiplier(multiplyBy){
   function multiply(num){
      return multiplyBy * num;
   }

   return multiply;
}

var multiplyByTwo = getMultiplier(2);
var multiplyByTen = getMultiplier(10);
var twoIntoFive = multiplyByTwo(5); // 10
var tenIntoSix = multiplyByTen(6);  // 60

所以内函数multiply可以访问外函数的参数multiplyBy。 外部函数getMultiplier返回一个可以用作乘数函数的函数。 我们正在创建两个函数multiplyByTwo和multiplyByTen。 在调用这两个函数时,JavaScript运行时会记住执行环境(getMultiplier函数的参数),并执行数字之间的乘法。

闭包在JavaScript和JavaScript的库和框架中广泛使用。 当您将内联函数写入事件处理程序或回调函数时,简单的例子就是事件处理和AJAX调用。 这些内联函数可以访问main(外部)函数的变量和参数。

以下是jQuery中按钮单击事件处理函数(闭包)的示例。 即使外部函数未执行,该函数也可以访问计数变量及其状态。

$(function(){
   var count = 1;
   $("#counterBtn").Click(function(){ 
                      alert("Your click count is: " + count++);
                    });
});

闭包也可用于定义可以访问JavaScript模块模式中的私有函数和变量的公共函数。 下面给出一个简单的例子。

var mathUtility = (function(){
   var count = 1;

   function increment(number){
      return number + count;
   }

   function decrement(number){
      return number - count;
   }

   return {
      nextOf: increment,
      previousOf: decrement
   };
}());

var numberAfterFive = mathUtility.nextOf(5);       // 6
var numberBeforeTen = mathUtility.previousOf(10);  // 9

我们创建了一个包含两个私有函数increment和decrement的模块mathUtility。 两个私有函数都可以访问外部匿名函数中的count变量,从而形成闭包。 return返回的对象,实际上是一个名为mathUtility的模块,它包含两个公共函数nextOf和previousOf,可以用于查找任何给定数字的下一个或前一个数字。以上就是对闭包的讲述。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值