理解闭包三个基本的事实

第一个事实: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. 从走出校门到Java实习生生活

    序 男,95年,这个学期就大四了,非计算机专业(数字媒体).目前在二线城市做Java实习生,待遇一般,应该算一个正常的实习生水平吧:租的一个约10平米的小单间,实习工资-衣食住行-杂七杂八的小消费差不 ...

  2. javascript基于原型实现面向对象

    传统的OO语言有类的概念,但js(ES5)却是基于原型实现的面向对象. 原型是?我们创建的每一个函数都会有一个原型(prototype)属性,这个属性是一个指针,指向函数的原型(prototype)对 ...

  3. Git.Framework 框架随手记--存储过程简化

    在很多的ORM中对存储过程操作都是一个棘手的地方,因为存储过程是一段预编译的代码,其中可以包含很多处理过程.在Git.Framework中也同样存在这样的问题,目前没有能力解决这个问题.但是对于存储过 ...

  4. Pell方程及其一般形式

    一.Pell方程 形如x^2-dy^2=1的不定方程叫做Pell方程,其中d为正整数,则易得当d是完全平方数的时候这方程无正整数解,所以下面讨论d不是完全平方数的情况. 设Pell方程的最小正整数解为 ...

  5. 21.C#序列过虑、排序、let子句和连接(十一章11.3-11.5)

    哈哈,隔了一个星期,再怎么样都要发一篇,要多看书啊,书不能停~~~ 使用where子句进行过虑 where子句的语法格式如下:where 过虑表达式 例子:新建一个珠宝类,如下: class Jewe ...

  6. angular的GitHub Repository Directive Example学习

    angular的GitHub Repository Directive Example学习 <!DOCTYPE html> <html ng-app="myApp" ...

  7. 获取request的变量

    由于IP代码未实现,先注释掉. package com.helloweenvsfei.servlet; import java.io.IOException; import java.io.Print ...

  8. "use strict"

    "use strict";//严格模式 <!doctype html> <html> <head> <meta charset=" ...

  9. iframe标签用法详解(属性、透明、自适应高度)

    1.iframe 定义和用法 iframe 元素会创建包含另外一个文档的内联框架(即行内框架). HTML 与 XHTML 之间的差异 在 HTML 4.1 Strict DTD 和 XHTML 1. ...

  10. Python 之我见

    读音 Python(KK 英语发音:/ˈpaɪθən/) 序言 其实早前就已经接触了python这个功能强大的脚本语言,但是那时只是基于兴趣而学习,目的性并不是很强,所以学习的并不是很深入.最近由于闲 ...