javascript閉包(Effective JavaScript讀書筆記)

來源:互聯網
上載者:User

標籤:

Effective JavaScript:編寫高品質JavaScript代碼的68個有效方法:

Item 11:   Get Comfortable with Closures 

Closures may be an unfamiliar concept to programmers coming from languages that don’t support them. And they may seem intimidating at first. But rest assured that making the effort to master closures will pay for itself many times over. 

Luckily, there’s really nothing to be afraid of. Understanding closures only  requires  learning  three  essential  facts.  The  first  fact  is  that JavaScript allows you to refer to variables that were defined outside of the current function

function  makeSandwich()  { var  magicIngredient  =  "peanut  butter"; function  make(filling)  { return  magicIngredient  +  "  and  "  +  filling;}return  make("jelly");}makeSandwich();  //  "peanut  butter  and  jelly" 

Notice how the inner make function refers to magicIngredient, a variable defined in the outer makeSandwich function. 

The  second  fact  is  that  functions  can  refer  to  variables  defined  in outer functions even after those outer functions have returned! If that sounds  implausible,  remember  that  JavaScript  functions  are  firstclass objects (see Item 19). That means that you can return an inner function to be called sometime later on: 

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" 

This  is  almost  identical  to  the  first  example,  except  that  instead of  immediately  calling  make("jelly")  inside  the  outer  function, sandwichMaker returns the make function itself. So the value of f is the inner make function, and calling f effectively calls make. But somehow, even though sandwichMaker already returned, make remembers the value of magicIngredient. 

How does this work? The answer is that JavaScript function values contain  more  information  than  just  the  code  required  to  execute when they’re called. They also internally store any variables they may refer  to  that  are  defined  in  their  enclosing  scopes.  Functions  that keep track of variables from their containing scopes are known as closures. The make function is a closure whose code refers to two outer variables: magicIngredient and filling. Whenever the make function is called, its code is able to refer to these two variables because they are stored in the closure. 

A  function  can  refer  to  any  variables  in  its  scope,  including  the parameters and variables of outer functions. We can use this to make a more general-purpose sandwichMaker: 

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

This example creates two distinct functions, hamAnd and turkeyAnd. Even though they both come from the same make definition, they are two distinct objects: The first function stores "ham" as the value of magicIngredient, and the second stores "turkey". 

Closures are one of JavaScript’s most elegant and expressive features, and are at the heart of many useful idioms. JavaScript even provides a more convenient literal syntax for constructing closures, the function expression: 

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

Notice that this function expression is anonymous: It’s not even necessary to name the function since we are only evaluating it to produce a  new  function  value,  but  do  not  intend  to  call  it  locally.  Function expressions can have names as well (see Item 14). 

The  third  and  final  fact  to  learn  about  closures  is  that  they  can update  the  values  of  outer  variables.  Closures  actually  store  references to their outer variables, rather than copying their values. So updates are visible to any closures that have access to them. A simple idiom that illustrates this is a box—an object that stores an internal value that can be read and updated: 

function  box()  { var  val  =  undefined; return  { set:  function(newVal)  {  val  =  newVal;  }, get:  function()  {  return  val;  }, type:  function()  {  return  typeof  val;  }  }; } var  b  =  box(); b.type();  //  "undefined" b.set(98.6); b.get();    //  98.6b.type();  //  "number" 

This example produces an object containing three closures: its set, get, and type properties. Each of these closures shares access to the val  variable.  The  set  closure  updates  the  value  of  val,  and  subsequently calling get and type sees the results of the update. 

 

Things to Remember 

? Functions can refer to variables defined in outer scopes. 
? Closures can outlive the function that creates them. 

? Closures  internally  store  references  to  their  outer  variables,  and can both read and update their stored variables. 

 

javascript閉包(Effective JavaScript讀書筆記)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.