码迷,mamicode.com
首页 > 编程语言 > 详细

javascript闭包(Effective JavaScript读书笔记)

时间:2015-06-21 23:35:33      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:

Effective JavaScript:编写高质量JavaScript代码的68个有效方法:

Item 11:   Get Comfortable with Closures 

Closures may be an unfamiliar concept to programmers coming from languages that dont 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, theres 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 theyre 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 JavaScripts 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: Its 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 boxan 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.6

b.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读书笔记)

标签:

原文地址:http://www.cnblogs.com/hghrpg/p/4592570.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!