最近工作之余匆忙去参加了一个面试,感觉可能是一直在工作,不太注意去总结一些知识点,所以回答的我不是特别满意,有一些专业术语和实际技术不能很快的联系起来,印象最深的就是闭包这个,JavaScript的一个特点,也算是一个难点吧,很容易说不清楚或者是理解有偏差,但是实际工作中,很多应用都需要依靠闭包来实现,因此,在此巩固一下。

一、变量作用域

首先,要理解闭包,必须理解JavaScript的变量作用域。

JavaScript变量的作用域分为两种:全局变量和局部变量。

什么是全局变量呢?全局变量就是在函数外部声明或者是不使用var命令直接声明的变量,全局变量作为window的一个属性。

什么是局部变量呢?局部变量就是在函数内部定义的变量。

1.函数内部可以直接读取全局变量。

var str = "Hello World!";
function fuc() { alert(str); }
fuc(); //Hello World

2.函数外部无法读取局部变量。

 function fuc() {var str = 'Hello World';}
alert(str); // error

Note:一定要养成使用var命令声明变量的习惯,因为如果在函数内部声明变量(期望声明一个局部变量),但是不适用var命令的话,实际上声明了一个全局变量。

function fuc() { str = "Hello World"; }
fuc();
alert(str); //Hello World

二、如何在函数外部读取局部变量?

上面说过,函数外部无法读取局部变量,但是,有些情况下我们需要得到函数内部的局部变量怎么办?

1.函数内部再定义一个函数:

function fuc() {var str = "Hello World";function fuc2() {alert(str);}return fuc2;
}
var result = fuc();
result(); //Hello World

这个示例中,fuc2函数被包括在函数fuc内部,这时候fuc函数内部的所有局部变量,对于fuc2都是可见的。但是fuc2内部的局部变量对于fuc则是不可见的。这就是JavaScript语言特有的“链式作用域”结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。

所以,既然fuc2可以读取fuc中的局部变量,那么只要把fuc2作为返回值,我们就可以在fuc外部读取它的内部变量了。

三、闭包

1.概念

什么是闭包呢?闭包就是能够读取其他函数内部变量的函数。在JavaScript语言中,只有函数内部的子函数才能读取局部变量,因此闭包也可以理解成“定义在一个函数内部的函数”。所以,本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

2.闭包的用途

(1)、在函数外部读取函数内部的变量

(2)、让函数内部的变量的值始终保持在内存中

function f1() {var n = 0;nAdd = function () { n += 1 }function f2() {alert(n);}return f2;
}
var result = f1();
result(); // 0
nAdd();
result(); // 1

此段代码,result就是闭包f2函数。它运行了两次,第一次的值是0,第二次的值是1.这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。

那么为什么会这样呢?原因在于f1是f2的父函数,而f2被赋给了一个全局变量,这导致f2始终在内存中,而f2的存在依赖于f1,因此f1也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。

这段代码中另一个值得注意的地方,就是"nAdd=function{n+=1;}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的变量进行操作。

四、使用闭包的注意事项

1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄漏。解决办法是,在退出函数之前,将不使用的局部变量全部删除。

2、闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当做对象(Object)使用,把闭包当做它的公用方法(Public Method),把内部变量当做它的私有属性(private value),这是一定要小心,不要随便改变父函数内部变量的值。

五、练习题

练习一:

var name = "The Window";
var obj = {name: "My Object",getNameFunc: function () {//this是指obj对象return function () {//this是指window对象return this.name; };}
};
alert(obj.getNameFunc()());

练习二:

var name = "The Window";
var object = {name: "My Object",getNameFunc: function () {var that = this;return function () {return that.name;};}
};
alert(object.getNameFunc()());

这两个练习题有一个比较值得注意的地方,this,一般而言,在JavaScript中,this指向函数执行时的当前对象,但是当没有明确的对象的时候,this就是指向全局对象window。

5.参考链接

[1] 阮一峰, 学习Javascript闭包(Closure)

转载于:https://www.cnblogs.com/zouyanzhi/p/5504688.html

学习JavaScript闭包相关推荐

  1. 前端知乎:关于阮一峰博客《学习Javascript闭包》章节中最后两个思考题

    阮一峰博客:<学习Javascript闭包>章节中最后有个思考题: 如果你能理解下面两段代码的运行结果,应该就算理解闭包的运行机制了. 代码片段一 var name = "The ...

  2. 通过示例学习JavaScript闭包

    译者按: 在上一篇博客,我们通过实现一个计数器,了解了如何使用闭包(Closure)**,这篇博客将提供一些代码示例,帮助大家理解闭包. 原文: JavaScript Closures for Dum ...

  3. js 点击闭包_学习Javascript闭包(Closure)

    讲的很清楚明了,连我都懂了,要是我们大学时的老师也能这么讲课...他们只会放幻灯片 2009年8月30日 22:29 | # | 引用 2009年8月30日 22:44 | # | 引用 呵呵,可以作 ...

  4. 阮一峰的学习Javascript闭包(Closure)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解 ...

  5. 学习Javascript闭包(Closure)(转载+理解心得)

    以前看了闭包的文章,感觉都没有这次理解的深刻,主要是说到了把"局部函数返回给了全局变量",而根据我的理解,全局变量是在内存里专门分配了一块. 从程序开始直到结束一直存在的,所以闭包 ...

  6. (转载)学习Javascript闭包(Closure)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascript初学者应该是很有用的. 一.变量的作用域 要理解 ...

  7. JavaScript学习总结(十六)——Javascript闭包(Closure)

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.很早就接触过闭包这个概念了,但是一直糊里糊涂的,没有能够弄明白JavaScript的闭包到底是什 ...

  8. javascript闭包—围观大神如何解释闭包

    闭包的概念已经出来很长时间了,网上资源一大把,本着拿来主意的方法来看看. 这一篇文章 学习Javascript闭包(Closure) 是大神阮一峰的博文,作者循序渐进,讲的很透彻.下面一一剖析. 1. ...

  9. 【javascript闭包】转载一篇不错的解释,也有几个大牛的链接

    初学闭包时一直以为很简单.但伴随对一个问题深入学习后,才算真正理解了闭包,同时也发现连<<JavaScript高级程序设计>>中都些不准确的地方. 我不准备从头介绍闭包的概念, ...

  10. JavaScript -- 闭包与作用域链

    目录 什么是闭包 作用域及作用域链 闭包的使用及作用 闭包的作用: 闭包不会产生内存泄漏: 闭包的应用: 闭包练习题 参考文章: 什么是闭包 红宝书上解释: 闭包 是指有权访问另外一个函数作用域中的变 ...

最新文章

  1. 关于睡眠你不可不知的十件事
  2. 基于MATLAB的面向对象编程(1)——类,属性,方法
  3. 绘制二次三次曲线多次曲线
  4. 《七哥说道》第二章:初出茅庐之拜师学艺
  5. Oracle推出支援.NET 3.5与Visual Studio 2008的开发工具
  6. CSS Sprites原理
  7. excel制作甘特图模板
  8. 布法罗纽约州立大学计算机排名,2019年QS世界大学排名纽约州立大学布法罗分校排名第313...
  9. 史上最牛的Linux视频教程—兄弟连 学习笔记1
  10. between and 用法
  11. PS如何快速简单的给人像美白
  12. 小码哥《恋上数据结构与算法》笔记(十五):哈希表(Hash Table)
  13. 动态规划算法学习(一)爬楼梯和凑金额
  14. strcmp函数的分析及实现
  15. 【javascript】class的继承之super的使用
  16. arduino按钮控制led,按一次亮,再按灭
  17. Python基于内存缓存简单实现
  18. java车辆租赁管理系统
  19. 检测网络是否稳定的计算机命令,怎么看电脑上网络丢包 查看网速有没稳定和网络是否延时方法...
  20. sheepdog--介绍

热门文章

  1. Linux学习之旅(二)Linux文档操作
  2. 关于我对区块链和比特币的看法
  3. 读书笔记 - 《漫威宇宙》
  4. 父子页面(iframe)相互获取对方dom元素
  5. javascript拾遗
  6. css_02 | CSS——CSS 选择器详解
  7. 【杂题总汇】HDU多校赛第十场 Videos
  8. C#获取数据库中某个字段的最大值
  9. TFS dataserver故障测试
  10. CS API 测试3