JavaScript闭包

来源:互联网 发布:gta5ol女神捏脸数据 编辑:程序博客网 时间:2024/05/17 19:22

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 innerFunctiondoSomething(); // 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); // 10var 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);       // 6var numberBeforeTen = mathUtility.previousOf(10);  // 9

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