| 
                                             闭包是什么? 闭包是内部函数可以访问外部函数的变量。它可以访问三个作用域:首先可以访问自己的作用域(也就是定义在大括号内的变量),它也能访问外部函数的变量,和它能访问全局变量。 
 
 内部函数不仅可以访问外部函数的变量,也能访问外部函数的参数(parameters)。但注意,它只能访问外部函数的 parameters ,而不能访问外部函数的 arguments 对象。 
 
 举例说明 JavaScript 闭包 
 
 function showName (firstName, lastName) {
   var nameIntro = "Your name is ";     // 内部函数可以访问外部函数的变量(nameInfo)、parameter (firstName、lastName)     function makeFullName () {
                 return nameIntro + firstName + " " + lastName;
         } 
 
     return makeFullName ();
 }
 
 
 showName ("Michael", "Jackson"); // Your name is Michael Jackson Jquery 闭包 
 
 $(function() {     var selections = [];     // 能访问 selections 变量     $(".niners").click(function() {         // 能更新变量 selections         selections.push (this.prop("name"));     }); }); 闭包的规则和副作用 即使是被返回的闭包仍然可以访问外部函数的变量 
 
 JavaScript 的执行时候的作用域和创建时候的作用域是一样的。这也就是说即使被外部函数返回后,内部函数仍然能访问外部函数的变量。 
 
 function celebrityName (firstName) {     var nameIntro = "This celebrity is ";    function lastName (theLastName) {         return nameIntro + firstName + " " + theLastName;     }     return lastName; } 
 
 var mjName = celebrityName ("Michael");// 这个时候外部方法 celebrityName 已经被返回了 
 
 // 闭包仍然可以访问外部方法的变量和参数 mjName ("Jackson"); // This celebrity is Michael Jackson
 闭包存储的是外部函数的变量的引用 
 
 存储的不是实际的值,在闭包被调用之前,如果外部函数中变量的值发生改变,会变得更有意思。 
 
 function celebrityID () {     var celebrityID = 999;     // 返回的包含内部函数的对象     return {         getID: function ()  {             // 内部函数返回的是更新以后的 celebrityID 变量值             return celebrityID;         },         setID: function (theNewID)  {             // 内部函数随时都能改变外部函数内的变量。             celebrityID = theNewID;         }     } } 
 
 var mjID = celebrityID (); // 此时,外部函数的 celebrityID 变量被改变。 mjID.getID(); // 999 mjID.setID(567); // 改变外部函数的 celebrityID 变量。 mjID.getID(); // 567 闭包的副作用 
 
 开发中有如下情况 
 
 function celebrityIDCreator (theCelebrities) {     var i;     var uniqueID = 100;     for (i = 0; i < theCelebrities.length; i++) {       theCelebrities[i]["id"] = function ()  {         return uniqueID + i;       }     } 
 
     return theCelebrities; } 
 
 var actionCelebs = [{name:"Stallone", id:0},     {name:"Cruise", id:0},     {name:"Willis", id:0} ]; 
 
 var createIdForActionCelebs = celebrityIDCreator (actionCelebs); 
 
 var stalloneID = createIdForActionCelebs [0]; 
 
 console.log(stalloneID.id()); // 103 在调用匿名函数的时候,uniqueID 已经加了 数字 3 变成 103,生成的 celebritiesID 也是 103,数组的每个元素也就是都是 103,而不是 100、101、102。 
 
 这是因为闭包(也即是例子中的内部匿名函数)访问的是外部函数的变量的引用,而不是变量的值。为了解决这个 BUG,我们可以使用一种 ** Immediately Invoked Function Expression ** (IIFE)(立即执行函数语法),代码如下: 
 
 function celebrityIDCreator (theCelebrities) {     var i;     var uniqueID = 100;     for (i = 0; i < theCelebrities.length; i++) {         theCelebrities[i]["id"] = function (j)  {             // 这里的 j 参数也就是在 调用(IIFE)时传过来的参数 i。             return function () {                 return uniqueID + j;                 // 依次接收传递过来 i 值,然后把它保存在数组中。             } () // 通过在 function 末尾处加 () ,可以立即执行它,然后只返回 uniqueID + j 的值,而不是 一个 function。         } (i); // 传递过来一个 i 变量作为匿名函数的参数,并立即执行它。     } 
 
     return theCelebrities; } 
 
 var actionCelebs = [{name:"Stallone", id:0}, {name:"Cruise", id:0}, {name:"Willis", id:0}]; 
 
 var createIdForActionCelebs = celebrityIDCreator (actionCelebs); 
 
 var stalloneID = createIdForActionCelebs [0]; 
 
 console.log(stalloneID.id); // 100 
 
 var cruiseID = createIdForActionCelebs [1];
 
 
 console.log(cruiseID.id); // 101 
  
                                         |