我同样也是个javascript新手,怎么说呢,先学的jquery,精通之后发现了javascript的重要性,再回过头来学javascript面向对象编程。

最近看了几篇有关javascript闭包的文章,包括最近正火的汤姆大叔系列,还有《javascript高级程序设计》中的文章,……我看不懂,里面有些代码是在大学教科书中看都没看过的,天书一般。幸好最近遇到两本好书《ppk on javascript》和《object-oriented JavaScript》,正字阅读中,后者还没有中文版,但前者还是建议看原版,写的不复杂,有兴趣的朋友可以看看,适合想进阶的朋友。

今天就结合这两本书,用最浅显的语言和最通俗的方式谈谈javascript中的闭包,因为也是新手,所以有有误的地方请各位指出,谢谢

一.   准备知识

1.函数作为函数的参数

在学习javascript中,你始终要有一个有学习与其他语言不同的概念:函数(function)不么特殊的东西,它也是一种数据,与bool ,string,number没有什么两样。

函数的参数可以string,number,bool如:

function(a, b) {return a + b;} 

但同样也可以传入函数。对你没有听错,函数的参数是函数!加入你有以下两个函数:

//把三个数翻一倍function multiplyByTwo(a, b, c) {var i, ar = [];

for(i = 0; i < 3; i++) {    ar[i] = arguments[i] * 2;  }return ar;}

//把数加一function addOne(a) {

return a + 1;

}

然后这么使用

var myarr = [];

//先把每个数乘以二,用了一个循环

myarr = multiplyByTwo(10, 20, 30);

//再把每个数加一,又用了一个循环

for (var i = 0; i < 3; i++) {myarr[i] = addOne(myarr[i]);}

要注意到其实这个过程用了两个循环,还是有提升的空间的,不如这么做:

function multiplyByTwo(a, b, c, addOne) {

var i, ar = [];

for(i = 0; i < 3; i++) {

    ar[i] = addOne (arguments[i] * 2);

  }return ar;}

这样就把函数当做参数传递进去了,并且在第一个循环中直接调用。这样的函数就是著名的回调函数(Callback function)

2.函数作为返回值

在函数中可以有返回值,但是我们一般都熟悉数值的返回,如

function ex(){

return 12

}

但你一旦意识到函数只是一种数据的话,你就可以想到同样可以返回函数。注意看下面这个函数:

function a() {

  alert('A!');

return function(){

    alert('B!');

  };

}

它返回了一个弹出”B!”的函数。接下来使用它:

var newFunc = a();newFunc();

结果是什么呢?首先执行a()的时候,弹出”A!”,此时newFunc接受了a的返回值,一个函数——此时newFunc就变成了那个被a返回的函数,再执行newFunc时,弹出”B!”

3.javascript的作用域

javascript的作用域很特别,它是以函数为单位的,而不是像其他语言以块为单位(如一个循环中),看下面这个例子:

var a = 1; function f(){var b = 1; return a;}

如果你此时试图想得到b的值:在firebug中试图输入alert(b)的话,你会得到错误提示:

b is not defined

为什么你可以这么理解:你所在的编程环境或者窗口是最顶级的一个函数,好像一个宇宙,但是b只是在你内部函数的一个变量,宇宙中的小星球上的一个点,你很难找到它,所以在这个环境中你不能调用它的;反之这个内部函数可以调用变量a,因为它暴露在整个宇宙中,无处藏身,同时也可以调用b,因为它就在自己的星球上,函数内部。

就上面这个例子说:

  1. 在f()外,a可见,b不可见
  2. 在f()内,a可见,b也可见

再复杂点:

var a = 1; //b,c在这一层都不可见

function f(){

var b = 1;

function n() { //a,b,c对这个n函数都可以调用,因为a,b暴露在外,c又是自己内部的

var c = 3;

  }

}

问你,函数b可以调用变量c吗?不行,记住javascript的作用域是以函数为单位的,c在n的内部,所以对f来说是不可见的。

开始正式谈闭包:

首先看这个图:

假设G,F,N 分别代表三个层次的函数,层次如图所示,a,b,c分别是其中的变量。根据上面谈到的作用域,我们有如下结论:

  1. 如果你在a点,你是不可以引用b的,因为b对你是不可见的
  2. 只有c可以引用b

闭包的吊诡之处的就在于发生了如下情况:

N突破了F的限制!跑到于a同一层了!因为函数只认它们在定义时所处的环境而不是执行时,这点很重要),N中的c仍然可以访问b!此时的a还是不可以访问b!

但是这是怎么实现的呢?如下:

闭包1

function f(){

var b = "b";

return function(){ //没有名字的函数,所以是匿名函数

return b;

  }

}

注意返回的函数可以访问它父亲函数中的变量b

此时如果你想取b的值,当然是undefined

但是如果你这么做:

var n = f();

n();

你可以取到b的值了!虽然此时n函数在f的外面,b又属于f内部的变量,但是f内部出了一个内鬼,返回了b的值……

现在大家有点感觉了吧

闭包2

var n;

function f(){

var b = "b";

  n = function(){

return b;

  }

}

如果此时调用f会怎么样?那就生成了一个n的全局范围函数,但是它却能访问f的内部,照样返回b的值,与上面有异曲同工之妙!

闭包3:

你还可以用闭包访问函数的参数

function f(arg) {

var n = function(){

return arg;

  };

  arg++;

return n;

}

此时如果使用:

var m = f(123);

m();

结果是124

因为此时f中返回的匿名函数经过了两道转手,先给n,再赋给外面的m,但本质没有变,把定义时父函数的参数返回了

闭包4

var getValue, setValue;

function() {

var secret = 0;

  getValue = function(){

return secret;

  };

  setValue = function(v){

    secret = v;

  };

})

运行:

getValue()

     0

setValue(123)

getValue()

     123

这个就不用解释了吧,如果你有面向对象语言基础的话(如C#),这里的getValue和setValue就类似于一个对象的属性访问器,你可以通过这两个访问器来赋值和取值,而不是能访问其中内容

其实书中还有几个闭包的例子,但是原理用上面四个就足够了,希望能起抛砖引玉的作用,给javascript进阶者对闭包有一个更深刻的理解

转载于:https://www.cnblogs.com/hh54188/archive/2012/03/01/2374921.html

用最通俗易懂的代码帮助新手理解javascript闭包相关推荐

  1. 让你分分钟理解 JavaScript 闭包

    原文:https://www.cnblogs.com/onepixel/p/5062456.html 让你分分钟理解 JavaScript 闭包 闭包,是 Javascript 比较重要的一个概念,对 ...

  2. 全面理解Javascript闭包和闭包的几种写法及用途--转载自https://www.cnblogs.com/yunfeifei/p/4019504.html...

    全面理解Javascript闭包和闭包的几种写法及用途 好久没有写博客了,过了一个十一长假都变懒了,今天总算是恢复状态了.好了,进入正题,今天来说一说javascript里面的闭包吧!本篇博客主要讲一 ...

  3. 深入理解JavaScript闭包(closure) 【收藏】

    深入理解JavaScript闭包(closure) 原文地址:http://www.felixwoo.com/archives/247  Felix Woo 最近在网上查阅了不少Javascript闭 ...

  4. (转)深入理解Javascript闭包(closure)

    深入理解Javascript闭包(closure) 一.什么是闭包?        "官方"的解释是:所谓"闭包",指的是一个拥有许多变量和绑定了这些变量的环境 ...

  5. 从λ演算到函数式编程聊闭包(2):彻底理解JavaScript闭包规则

    闭包是很多语言都具备的特性,上篇<从抽象代数漫游函数式编程(1):闭包概念再Java/PHP/JS中的定义> 闭包的特性 闭包有三个特性: 函数嵌套函数 函数内部可以引用外部的参数和变量 ...

  6. 【译】理解JavaScript闭包——新手指南

    闭包是JavaScript中一个基本的概念,每个JavaScript开发者都应该知道和理解的.然而,很多新手JavaScript开发者对这个概念还是很困惑的. 正确理解闭包可以帮助你写出更好.更高效. ...

  7. 全面理解Javascript闭包和闭包的几种写法及用途【转】

    一.什么是闭包和闭包的几种写法和用法 1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点: 1. ...

  8. 全面理解Javascript闭包和闭包的几种写法及用途

     一.什么是闭包和闭包的几种写法和用法 1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点: 1. ...

  9. [转载]深入理解JavaScript闭包(closure)

    最近在网上查阅了不少Javascript闭包(closure)相关的资料,写的大多是非常的学术和专业.对于初学者来说别说理解闭包了,就连文字叙述都很难看懂.撰写此文的目的就是用最通俗的文字揭开Java ...

  10. 深入理解Javascript闭包(一)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用于.变量作用域包括 ...

最新文章

  1. 帕金森患者的新曙光!AI无线智能探测系统诞生
  2. .NET/ASP.NET Routing路由(深入解析路由系统架构原理)
  3. electron项目中使用jquery不生效的解决方法
  4. 【原创】kafka client源代码分析
  5. ai背景合成_AI设计制作万圣节夜景插画
  6. 一篇文章指明做JavaWeb项目需要的前置知识+完整项目初解读(萌新必看,十分友好)
  7. RT-Thread在github上的教程中图片显示不出来问题的解决方法
  8. 一种在旧代码上增加新需求的重构模式
  9. Zabbix监控Nginx连接状态
  10. Linux下禁止使用swap及防止OOM机制导致进程被kill掉
  11. python精妙算法_YOLOv4:高速物体检测的精妙之处
  12. vivo S12 PRO怎么解锁vivoS12解锁平台刷机教程屏幕锁激活手机锁不记得了可以用这个方法教程刷机解锁用的
  13. Java一般操作 对象序列化和反序列化
  14. 抖音实战~搜索页面~扫描二维码
  15. OpenCV 文字检测与识别模块
  16. ACAD DWG to PDF Converter 9.8.2.4版本更新啦
  17. Java后端校验框架oval与hibernatevalidator的使用
  18. RDSDRDSPolarDBPolarDB-X的区别
  19. 数据结构与算法分析 收获总结 第1章 数据结构和算法
  20. Foxit Reader以及Foxit Phantom如何设置页面固定大小

热门文章

  1. 夜神模拟器android 8.0,夜神模拟器6.0.8.0
  2. 【夜神模拟器运行app】uniapp将app运行到夜神模拟器
  3. 使用DFA算法模型构建敏感词过滤器
  4. 通过Flex布局实现三等分
  5. 基于java的小额支付管理平台
  6. 06 Halcon 点云平面度测量
  7. 主题:讲解三层代码讲解--第三课(*****) DATE:2004-05-28
  8. 两阶段最小二乘法原理_什么是两阶段最小二乘法(2sls)?
  9. html投影电脑,如何将电脑内容显示到投影仪或电视上?详细教程奉上
  10. 【解决方案】Ubuntu18.04 安装L2TP及相关设置