javascript闭包(Effective JavaScript读书笔记)

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.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.

时间: 2025-01-05 16:14:10

javascript闭包(Effective JavaScript读书笔记)的相关文章

《Javascript 设计模式》-读书笔记

第七章   设计模式类别 一.设计模式有三种类别 1.创建型模式:专注于处理对象机制.包括:构造器.工厂.抽象.原型.单例.生成器 2.结构型模式:用于找出在不同对象之间建立关系密切的简单方法. 包括:装饰者.外观.享元.适配器.代理 3.行为模式:用于改善或简化系统中不同对象之间的通信.包括:迭代器.中介者.观察者.访问者 第八章   设计模式分类 <Javascript 设计模式>-读书笔记,布布扣,bubuko.com

《javascript权威指南》读书笔记——第二篇

<javascript权威指南>读书笔记--第二篇 金刚 javascript js javascript权威指南 今天是今年的196天,分享今天的读书笔记. 第2章 词法结构 2.1 字符集 JavaScript程序是用Unicode字符集编写. Unicode是ASCII和Latin-1的超集,支持几乎所有语言. ES3 要求支持Unicode 2.1及后续版本 ES5 要求支持Unicode 3及后续版本 2.1.1 区分大小写 JavaScript是区分大小写的. HTML 并不区分大

Javascript DOM 编程艺术读书笔记16/04/01

愚人节快乐 开始用webstorm了,随着学习深入,代码越来越长,因为不借助ide还真是挺难的 今天发现了一个严重的误区,text和textNode是完全不同的两个概念,之前没有特别注意,写代码很容易跳过createTextNode直接用parentNode.appendChild(text) 单独拎出来晒一晒,以后引以为戒 Javascript DOM 编程艺术读书笔记16/04/01

《javascript权威指南》读书笔记——第一篇

<javascript权威指南>读书笔记--第一篇 金刚 javascript js javascript权威指南 由于最近想系统学习下javascript,所以开始在kindle上看这本书来补充下. 今天是今年的196天,由于我之前承诺过,每天分享读书笔记,只是之前分享的是大众读物,所以随手分享到kindle阅读群里了.但是现在读的是技术类书籍,分享到kindle读书群不太合适,所以还是以博客的形式分享.这样子,一个链接,大家感兴趣了就点开看看,不感兴趣了,就不点开. 其实这篇文章应该是昨天

JavaScript DOM编程艺术 读书笔记

3 DOM DOM分别指document,object和model. DOM中包含的节点主要分为三种:元素节点.文本节点和属性节点.DOM的原子是元素节点,标签的名字就是元素的名字,元素可以包含其他的元素.没有被包含在其他元素里的唯一元素是<html>元素,它是树节点的根元素:在XHTML文档里,文本节点总是被包含在元素节点的内部.但并非所有的元素节点都包含有文本节点:属性节点用来对元素做出更具体地描述. 有3种DOM方法可获取元素节点,分别是通过元素ID.通过标签名字和通过类名字来获取. 1

Professional JavaScript for Web Developers 读书笔记

Chapter 6 OBJECT-ORIENTED PROGRAMMING Object Creation the constructor pattern Object created by the constructor function that using new key will automatically have a constructor property(non-enumerable) which points to the constructor How prototype w

《JavaScript 高级程序设计》读书笔记一 简介

一   历史 二   实现 a. javascript三个部分: ECMAScript:由ECMA-262定义,提供核心语言功能: DOM:提供HTML的应用程序编程接口/提供访问和操作网页内容的方法和接口: BOM:提供与浏览器交互的方法和接口: 三   版本 <JavaScript 高级程序设计>读书笔记一 简介

《JavaScript 高级程序设计》读书笔记二 使用JavaScript

一   <script>元素 a.四个属性: async:立即异步加载外部脚本: defer:延迟到文档完全被解析再加载外部脚本: src:外部脚本路径: type:脚本语言的内容类型: 二   XHTML中用法 a. //<![CDATA[ javascript代码 //]]> 三   <noscript>元素 <JavaScript 高级程序设计>读书笔记二 使用JavaScript

《JavaScript高级程序设计》读书笔记--前言

起因 web编程过程使用javascript时感觉很吃力,效率很低.根本原因在于对javascript整个知识体系不熟,看来需要找些书脑补一下,同时欢迎众网友监督. 大神推荐书籍 看了博客大神们推荐的javascript书籍和推荐的阅读顺序,如下所示: 从头到尾对一遍<<Javascript高级程序设计>>,不懂的地方可以暂时掠过,给自己对javascript有一个大体的印象 认认真真的读完这本书:<<编写可维护的javascript>>,从编码规范,技巧,

Effective Objective-C 读书笔记

一本不错的书,给出了52条建议来优化程序的性能,对初学者有不错的指导作用,但是对高级阶段的程序员可能帮助不是很大.这里贴出部分笔记: 第2条: 使用#improt导入头文件会把头文件的内容全部暴露到目标文件中,而且如果两个类之间存在循环引用则会出现编译错误,所以要尽量使用@class进行类声明. 如果需要实现一个协议,则必须#improt这个协议的头文件,所以可以将协议单独定义在一个.h文件当中.如果这个协议是代理模式协议的一部分,即需要与类捆绑使用才有实际意义,则建议定义在类当中,并以类名为前