便写高质量JavaSript的68个高效方法 >> 二章:变量作用域 >> 第11条:熟练掌握闭包

二章

第11条:熟练掌握闭包

理解闭包的三个基本事实:

1. javaSricpt允许你引用在当前函数以外定义的变量。

2. 即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。

3. 闭包可以更新外部变量的值。

1. javaSricpt允许你引用在当前函数以外定义的变量。

function makeSandwich(){

  var magicIngredient = "peanut butter";

  function make(filling){

    return magicIngredient + "and" + filling;

  }

  return make("jelly");

}

makeSandwich();      //"peanut butter and jelly"

请注意内部的make函数是如何引用定义在外部makeSandwich函数内的magicIngredient变量的。

2. 即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。

function sandwichMaker(){

  var magicIngredient = "peanut butter";

  function make(filling){

    return magicIngredient + "and" + filling;

  }

  return make;

}

var f = sandwichMaker();

f("jelly");    //"peanut butter and jelly"

f("bananas");     //"peanut butter and bananas"

f("marshmallows")     //"peanut butter and marshmallows"

与 1 的不同之处:f的值为内部的make函数,调用f实际上是调用make函数。

        即使sandwichMaker函数已经返回,make函数仍能记住magicIngredient的值。

这是如何工作的:JavaScript的函数值包含了比调用他们时执行所需要的代码还要多的信息。而且,JavaScript函数值还在内部存储他们可能会引用的定义在其封闭作用域的变量。那些在其所涵盖的作用域内跟踪变量的函数被称为闭包。

make函数就是一个闭包,其代码引用了两个外部变量:magicIngredient 和filling。每当make函数被调用时,其代码都能引用到这两个变量,因为该闭包存储了这两个变量。

函数可以引用在其作用域内的任何变量,包括参数和外部函数变量。

更加通用的sandwichMaker函数

function sandwichMaker(magicIngredient){  
  function make(filling){     
    return magicIngredient + "and" + filling;   
  }   return make; 
} 
var handAnd = sandwichMaker("ham"); 
handAnd("cheese");        //"ham and cheese" 
handAnd("mustard");             //"ham and mystard" 
var turkeyAnd = sandwichMaker("turkey"); 
turkeyAnd("Swiss");    //"turkey and Swiss"
turkeyAnd("Provolone");  //"turkey and provolone" 

函数表达式(更方便地构建闭包的字面量语法)

function sandwichMaker(magicIngredient){  
  function make(filling){     
    return magicIngredient + "and" + filling;   
  }  
} 

3. 闭包可以更新外部变量的值。

  实际上,闭包存储的是外部变量的引用,而不是他们的值的副本。

  因此对于任何具有访问这些外部变量的闭包,都可以进行更新。

一个简单的惯用法box对象的例子。(他存储了一个可读写的内部值)

 

 function box(){

    var val = unfefined;

     return {

        set:function(newVal){ val = newVal; },

        get:function(){ return val; },
        type:function(){ return val; }
     };
  }

  var b = box();

  b.type();     //"undefined"
  b.set(98.6);     

  b.get();    //98.6
  b.type();     //"number"
这个例子产生了一个包含三个闭包的对象。
这三个闭包是set、get、type属性。他们都共享访问val变量。set闭包更新val的值,随后调用get和type查看更新的结果。

提示:

  • 函数可以引用定义在其外部作用域的变量。
  • 闭包比创建他们的函数有更长的生命周期。
  • 闭包在内部存储其外部变量的引用,并能读写这些变量。
原文地址:https://www.cnblogs.com/meiyanstar/p/13091346.html