一、闭包(Closure)

1.1、什么是闭包?

理解闭包概念:

a、闭包是指有权限访问另一个函数作用域的变量的函数,创建闭包的常见方式就是在一个函数内部创建另一个函数,也就是创建一个内部函数,创建一个闭包环境,让返回的这个内部函数保存要引用的变量,以便在后续执行时可以保持对这个变量的引用。

b、只要存在调用内部函数的可能,JavaScript就需要保留被引用的函数。而且JavaScript运行时需要跟踪引用这个内部函数的所有变量,直到最后一个变量废弃,JavaScript的垃圾收集器才能释放相应的内存空间。

c、Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。

d、如果一个内部函数被调用且引用了它的外部变量那么它就是一个闭包。

相信你看了上面的这段话可能还不理解什么是闭包,那么我就举一个闭包的经典例子来帮助你理解闭包的概念吧。

请看下面这段代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>闭包</title>
</head>
<body>
<script type="text/javascript">
function out() {
var i = 0;
function inner() {
alert(++i);
}
return inner;
}
var ref= out();
ref();
</script>
</body>
</html>

结果:

上面的代码有两个特点:
1、创建两个函数out,inner,函数inner嵌套在函数out内部,也可以说是函数inner是函数out的内部函数;
2、调用函数out返回内部函数inner。
这样在执行完var ref=out()后,变量ref实际上是指向了函数inner,也可以说是引用了函数inner,再执行ref()后就会看到上图弹出一个窗口显示i的值第一次为1。

这段代码其实就创建了一个闭包,为什么?因为函数out外的变量ref引用了函数out内部的函数inner,也就是说:

当函数out的内部函数inner被函数out外的一个变量ref引用的时候,就创建了一个闭包。

可能你还是不理解闭包这个概念,因为你不知道闭包有什么用,那么先理解一下闭包的作用吧。

1.2、为什么要用闭包(作用)?

1.2.1、保护函数内的变量安全。

解释:以上面的的例子为例,函数out中i只有函数innder才能访问,而无法通过其他途径访问到,因此保护了i的安全性。

1.2.2、通过访问外部变量,闭包可以保存这些变量的上下文环境

在上面的示例中增加了一次函数ref()的调用,执行的结果如下:

解释:当函数out执行完并且最终退出时,它的局部变量会被Javascript的垃圾回收机制回收所占用的资源,也就是局部变量被销毁,但是因为创建了闭包环境,那么内部函数inner就会暂时保存外部函数的局部变量上下文环境。不会被垃圾回收机制回收。所以函数out中的i被复制一份暂时保存下来,这样每次执行ref(),i都是自加1后alert输出i的值。这只是我对闭包作用的简单初浅理解,不专业也不严谨,但大概意思就是这样,理解闭包需要循序渐进的过程。

相信你看了闭包的作用,对理解什么是闭包是否更明白一些,如果还是很疑惑,那么我就再举几个闭包的经典例子来帮助你理解闭包的概念吧。

1.3、闭包的经典示例

1.3.1、示例一

问题:假如我们有如下需求请在页面中放10个div,每个div写上对应的数字,当点击每一个div时显示索引号,如第1个div显示0,第10个div显示9。

可能你会这样做:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>闭包</title>
<style type="text/css">
div {
width: 50px;
height: 50px;
background: lightcoral;
float: left;
margin: 20px;
font: 15px/50px "microsoft yahei";
text-align: center;
}
</style>
</head>
<body>
<div>div-1</div>
<div>div-2</div>
<div>div-3</div>
<div>div-4</div>
<div>div-5</div>
<div>div-6</div>
<div>div-7</div>
<div>div-8</div>
<div>dvi-9</div>
<div>div-10</div>
<script type="text/javascript">
var divs=document.getElementsByTagName("div");
for (var i=0;i<divs.length;i++) {
divs[i].onclick=function(){
alert(i);
}
}
</script>
</body>
</html>

结果:

从上面的结果你会发现,不管你点击了哪个div,弹出的框div索引总是10,这可能会让你很意外,会产生疑惑,为什么会出现这样的结果呢?

解释:因为点击事件的函数内部使用外部的变量i一直在变化,当我们指定click事件时并没有保存i的副本,这样做也是为了提高性能,但达不到我们的目的,我们要让他执行的上下文保存i的副本,这种机制就是闭包。

使用闭包可以解决此问题,代码做了如下修改:

<script type="text/javascript">
var div=document.getElementsByTagName("div");
for (var i = 0; i < div.length; i++) {
div[i].onclick=function(n){
              return function(){
alert(n);//产生闭包,引用外部变量。
}
}(i);
}
</script>

结果:

从上面的结果你会发现,使用闭包后,就达到你预期的结果了。

解释:n是外部函数的值,但是内部函数需要使用这个值,因为产生闭包执行环境,所以返回函数前的n被临时驻留在内存中给点击事件使用,简单说就是函数的执行上下文被保存起来,i生成了多个副本。

1.3.2、示例二

示例代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<script type="text/javascript">
function out() {
var i = 10;
return function inner() {
i++;
alert(i);//引用了外部变量,创建了闭包环境
};
}
//此处为函数调用,第一个括符为调用out方法,第二个括符为调用返回的inner方法。
out()();
</script>
</body>
</html>

运行 结果:

1.3.3、示例三

示例代码:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>闭包</title>
</head>
<body>
<script type="text/javascript">
var name = "this is Window";  
var obj = {    
name: "My Object",
getNameFunc: function() {  
alert(this.name);//输出My Object
return function() {        
return this.name;      
};    
}  
};  
var funn=obj.getNameFunc();
alert(funn());//输出this is Window
</script>
</body>
</html>

运行结果:

解释:funn是属于方法调用,所以this绑定到了obj对象,自然this.name就是"My Object",但是闭包函数无法访问这个this,它只能访问到全局的this,所以this.name就是“this is Window”.

总结:相信通过以上是几个闭包示例,你对闭包也有一定的理解了吧。限于本人才疏学浅,对闭包的理解也并不是很透彻,只是理解了一些表面,会使用而已。若你想理解的更深入推荐你去看stackoverflow这个网站上对闭包的解释:http://stackoverflow.com/questions/111102/how-do-javascript-closures-work

JavaScript学习总结——我所理解的JavaScript闭包的更多相关文章

  1. web前端学习(四)JavaScript学习笔记部分(1)-- JavaScript基础教程

    1.JavaScript基础教程 1.1.Javascript基础-介绍.实现.输出 1.1.1.JavaScript是互联网上最流行的脚本语言,这门语言可用于web和HTML,更可广泛用于服务端.p ...

  2. javascript学习(1)用户的Javascript 放在哪里和函数的绑定方式

    一.实验 1:js脚本放在那里最合适? 1.代码 1.1.test.html <!DOCTYPE html><html>    <head>        < ...

  3. web前端学习(四)JavaScript学习笔记部分(10)-- JavaScript正则表达式

    1.JavaScript正则表达式课程概要 方便查找字符串.数字.特殊字串等等 2.正则表达式的介绍 RegExp是正则表达式的缩写 当检索某个文本时,可以使用一种模式来描述要检索的内容.RegExp ...

  4. web前端学习(四)JavaScript学习笔记部分(8)-- JavaScript 浏览器对象

    1.window对象 1.1.window对象: window对象是BOM的核心,window对象指当前的浏览器窗口 所有javaScript全局对象.函数以及变量均自动生成为window对象的成员 ...

  5. web前端学习(四)JavaScript学习笔记部分(3)-- JavaScript函数+异常处理+事件处理

    1.Javascript函数-了解函数的用途 1.1.函数: 函数是由事件驱动的或者当它被调用时执行的可重复使用的代码块 2.Javascript函数-定义函数 2.1.function必须小写 3. ...

  6. web前端学习(四)JavaScript学习笔记部分(2)-- JavaScript语法详解

    2.1.Javascript语法-运算符(1) 复数运算符 %取余 ++ -- 赋值运算符 += -= *= /= %= 字符串操作 <!DOCTYPE html> <html la ...

  7. web前端学习(四)JavaScript学习笔记部分(9)-- JavaScript面向对象详解

    1.认识面向对象 1.1.概念 1.一切事物皆是对象 2.对象具有封装和继承特性 3.信息隐藏(类的信息隐藏,包括属性和方法) <!DOCTYPE html> <html lang= ...

  8. web前端学习(四)JavaScript学习笔记部分(8)-- JavaScript瀑布流

    index.html <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type&qu ...

  9. web前端学习(四)JavaScript学习笔记部分(7)-- JavaScript DOM对象控制HTML元素详解

    1.方法 getElementsByName() 获取name 可以获取一个数组类型数据(参数加引号) getElementsByTagName() 获取元素   getAttribute() 获取元 ...

随机推荐

  1. NPM如何更新到最新版

    参考文章--npm更新到最新版本的方法 其实我们可以这样,随便新建一个文件夹例如:F:\test.按着"shift"键,右键该文件夹,选择"在此处打开命令窗口(W)&qu ...

  2. Linux 权限设置chmod

    Linux中设置权限,一般用chmod命令 1.介绍 权限设置chmod 功能:改变权限命令.常用参数: 1=x(执行权execute) 2=w(写权write) 4=r(读权Read) setuid ...

  3. Linux服务器安全配置

    众所周知,网络安全是一个非常重要的课题,而服务器是网络安全中最关键的环节.Linux被认为是一个比较安全的Internet服务器,作为一种开放源代码操作系统,一旦Linux系统中发现有安全漏洞,Int ...

  4. GO基础(二)

    本例中梳理go语言中的协程和通道. package main import ( "fmt" "time" ) //func01.func02 为演示同步机制 f ...

  5. Microsoft SQL Server中的事务与并发详解

    本篇索引: 1.事务 2.锁定和阻塞 3.隔离级别 4.死锁 一.事务 1.1 事务的概念 事务是作为单个工作单元而执行的一系列操作,比如查询和修改数据等. 事务是数据库并发控制的基本单位,一条或者一 ...

  6. HackerNews——《Pokemon Go玩家存在巨大的安全风险》

    译者注:原文来自HackerNews,首发tumblr,标题为Pokemon Go is a huge security risk.作者Adam Reeve,附一张这个胖子的帅照   (正文)之所以会 ...

  7. React 其实比 MVVM 架构更加卡顿

    React 号称通过引入 Virtual DOM 带来了性能的提升,而其实 React 之所以需要 Virtual DOM,是因为它的架构下,state 的变更是全量的,然后触发 render 返回全 ...

  8. CSharpGL(9)解析OBJ文件并用CSharpGL渲染

    CSharpGL(9)解析OBJ文件并用CSharpGL渲染 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo ...

  9. Java基础知识(壹)

    写在前面的话 这篇博客,是很早之前自己的学习Java基础知识的,所记录的内容,仅仅是当时学习的一个总结随笔.现在分享出来,希望能帮助大家,如有不足的,希望大家支出. 后续会继续分享基础知识手记.希望能 ...

  10. Web 存储

    Web Storage 介绍 Web storage 是在web上存储数据的功能,这里的存储是针对客户端来说的. 具体说分为两种: seesionStorage 数据存储在 session 对象中.s ...