理解闭包三个基本的事实

第一个事实:js允许你引用在当前函数以外定义的变量。

function makeSandwich(){

var magicIngredient=”peanut butter”;

function make(filling){

return magicIngredient+’and ’+filling;

}

return make(‘jelly’);

}

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

图上直接指出如下

第二个事实:即使外部函数已经返回,当前函数仍然可以引用在外部函数所定义的变量。

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”

还是上图标识

原理:js的函数值包含了比调用它们时执行所需要的代码还要多的信息。而且js函数值还在内部存储它们可能会引用的定义在其封闭作用域的变量。那些在其所涵盖的作用域内跟踪变量的函数被称为闭包。make函数就是一个闭包。其代码引用了两个外部变量:magicIngredient和filling。每当make被调用时,其代码都能引用到这两个变量,因为该闭包存储了这两个变量。

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

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(“trukey”);

turkeyAnd(“Swiss”);//”trukey and Swiss”

turkeyAnd(“Provolone”);//”trukey and Provolone”

闭包是js最优雅、最有表现力的特性之一,也是许多惯用法的核心。js还提供了一种更为方便构建闭包的字面量语法--函数表达式。

function sandwichMaker(magicIngredient){

return function(filling){

return magicIngredient+”and ”+filling;

}

}

请注意,该函数表达式是匿名的。由于只需要产生一个新值,而不需要在局部使用,所以没必要给该函数命名。

第三个事实:闭包可以更新外部变量的值。

实际上,闭包存储的是外部变量的引用,而不是它们的值的副本。因此任何具在访问这些外部变量的闭包,都可以进行更新。

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”

这个例子里产生了一个包含三个闭包的对象。这三个闭包是set,get和type属性。它们共享访问val变量。

提示

  • 函数可以引用定义在其外部作用域的变量
  • 闭包比创建它们的函数有更长的生命周期
  • 闭包在内部存储其外部变量的引用,并能读写这些变量

后记

这个部分,这觉得这里讲得已经很清楚,如果想再深入去了解,可以去看高3上面关于闭包的讲解。

里面对作用域链,执行环境,变量对象,都有详细说明。

[Effective JavaScript 笔记] 第11条:熟练掌握闭包的更多相关文章

  1. [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码

    函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...

  2. [Effective JavaScript 笔记]第35条:使用闭包存储私有数据

    js的对象系统并没有特别鼓励或强制信息隐藏.所有的属性名都是一个字符串,任意一个程序都可以简单地通过访问属性名来获取相应的对象属性.例如,for...in循环.ES5的Object.keys()和Ob ...

  3. [Effective JavaScript 笔记] 第4条:原始类型优于封闭对象

    js有5种原始值类型:布尔值.数字.字符串.null和undefined. 用typeof检测一下: typeof true; //"boolean" typeof 2; //&q ...

  4. [Effective JavaScript 笔记] 第5条:避免对混合类型使用==运算符

    “1.0e0”=={valueOf:function(){return true;}} 是值是多少? 这两个完全不同的值使用==运算符是相等的.为什么呢?请看<[Effective JavaSc ...

  5. [Effective JavaScript 笔记]第28条:不要信赖函数对象的toString方法

    js函数有一个非凡的特性,即将其源代码重现为字符串的能力. (function(x){ return x+1 }).toString();//"function (x){ return x+ ...

  6. [Effective JavaScript 笔记]第50条:迭代方法优于循环

    "懒"程序员才是好程序员.复制和粘贴样板代码,一但代码有错误,或代码功能修改,那么程序在修改的时候,程序员需要找到所有相同功能的代码一处处进行修改.这会使人重复发明轮子,而且在别人 ...

  7. [Effective JavaScript 笔记]第19条:熟练掌握高阶函数

    高阶函数介绍 高阶函数曾经是函数式编程的一个概念,感觉是很高深的术语.但开发简洁优雅的函数可以使代码更加简单明了.过去几年中脚本语言采用了这些个技术,揭开了函数式编程的最佳惯用法的神秘面纱.高阶函数就 ...

  8. [Effective JavaScript 笔记]第68条:使用promise模式清洁异步逻辑

    构建异步API的一种流行的替代方式是使用promise(有时也被称为deferred或future)模式.已经在本章讨论过的异步API使用回调函数作为参数. downloadAsync('file.t ...

  9. [Effective JavaScript 笔记]第46条:使用数组而不要使用字典来存储有序集合

    对象属性无序性 js对象是一个无序属性集合. var obj={}; obj.a=10; obj.b=30; 属性a和属性b并没有谁前谁后之说.for...in循环,先输出哪个属性都有可能.获取和设置 ...

随机推荐

  1. 【MPI学习6】MPI并行程序设计模式:具有不连续数据发送的MPI程序设计

    基于都志辉老师<MPI并行程序设计模式>第14章内容. 前面接触到的MPI发送的数据类型都是连续型的数据.非连续类型的数据,MPI也可以发送,但是需要预先处理,大概有两类方法: (1)用户 ...

  2. UEditor编辑文章出现多余空行问题的解决办法

    网站后台管理编辑文章以后,保存.再次打开编辑是文章前后多出多余的空行.一直以为是编辑器有问题,也没在意,但是自己编辑文章多了,感觉太麻烦了.想一定可以解决这个问题.百度一下果然找到原因.原来是加载编辑 ...

  3. Visual Studio调试

    一:C# CODING 技巧 1:TODO 然后 CTRL + W + T,打开任务列表,选中 Comments,就会显示所有待做的任务 2:打开所在的文件夹 右键单击任何一个文件选项卡, 选择&qu ...

  4. 在线富文本编辑器kindeditor配置(.Net Framework 3.5)

    下载地址:http://kindeditor.net/down.php 解压放在项目要目录下, 在Bin目录下添加引用:LitJSON.dll 在页面头部加: <link rel="s ...

  5. js验证函数摘录

    /**本文摘自:http://www.cnblogs.com/rob0121/articles/1776298.html * js各种表单数据验证 */ /********************** ...

  6. 02.C#可空類型、默認參數、LINQ(一章1.3-1.4)

    利用上班時間發個隨筆,不知領導會不會看到,可能會有同事看到也說不定啊:) 關于可空類型,在C#1中沒有這個概念,在C#3中引入的.那比如我們要實現一個表示人的類,人有名字和年齡兩個屬性,如何表示一個沒 ...

  7. [设计模式] javascript 之 建造者模式

    建造者模式说明 1. 将一个复杂对象的 构造 与它的表示相分离,使同样的创建过程可有不同的表示,这就叫做建造者模式. 2. 面向对象语言中的说明,主要角色: 1>. Builder 这个接口类, ...

  8. Grovvy初识

    1.Groovy和Java对比 Groovy的松散的语法允许省略分号和修饰符 除非另行指定,Grovvy的所有内容都为public Grovvy允许定义简单脚本,同时无需定义正规的class对象 Gr ...

  9. 每天一个linux命令(32):wc命令

    Linux系统中的wc(Word Count)命令的功能为统计指定文件中的字节数.字数.行数,并将统计结果显示输出. 1.命令格式: wc [选项]文件... 2.命令功能: 统计指定文件中的字节数. ...

  10. Throwable和Exception的区别

    Java语言要求java程序中(无论是谁写的代码)所有抛出(throw)的异常都必须是从Throwable派生而来.当然,实际的Java编程中,由于JDK平台已经为我们设计好了非常丰富和完整的异常对象 ...