Javascript的一个特殊点就在于它的闭包和回调特性,这两个特性让初学Javascript的我是云里雾里,至今仍在苦苦摸索与理解。在一番苦思之后,整理了一下资料,将自己的理解思路记录下来,以免今后糊涂的时候再次作为索引,也希望能给和我同样的初学者带来理解上的一点帮助。

    要清楚地理解闭包,首先要有如下几个概念需要清楚:

作用域:
    作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。

一切解释都没有例子来的清楚明白:

function say_hello(){
var words = "hello world!";
alert(words);
}
这里变量words的作用域就是括号“{”和“}”之间的范围。

作用链域:
    简单来说就是如果函数中需要用到的参数在本函数中有,则用本函数中的参数,如果没有则查询上一级函数中是否有,有则用之,没有则再次向上一级查询,直至找到或找不到为止(从最内层到最外层都没有)。这里不再多说,详细的说明见:Javascript中的作用链域
    继续看例子:
var str = "outer";
function outerFun(){
var str = "inner";
alert("------1------"+str);
function innerFun(){
str +="_new";
alert("------2------"+str);
}
innerFun();
alert("------3------"+str);
}
outerFun();
alert("------4------"+str);
//输出结果
------4------outer
------1------inner
------2------inner_new
------3------inner_new

这里可以看出函数outerFun内定义了str,但是最后的alert出的str却是“------4------outer",这说明外面是访问不到里面的变量,就是outerFun函数中的变量str的作用域在outerFun函数的花括号之间;但innerFun函数中

却可以访问外面outerFun中的str,这就是作用链域的作用了,即,本作用域内不存在的变量,就向上一级进行查找,如果该例子中outerFun中没有定义str,

那么就会是如下的情形:

var str = "outer";
function outerFun(){
alert("------1------"+str);
function innerFun(){
str +="_new";
alert("------2------"+str);
}
innerFun();
alert("------3------"+str);
}
outerFun();
alert("------4------"+str);
//输出结果
------4------outer
------1------outer
------2------outer_new
------3------outer_new
js的内存回收机制:
    一般一个函数在执行开始的时候,会给其中定义的变量划分内存空间保存,以备后面的语句所用,等到函数执行完毕返回了,这些变量就被认为是无用的了,对应的内存空间也就被回收了。下次再执行此函数的时候,所有的变量又回到最初的状态,重新赋值使用。
    但是,在Javascript中存在闭包的情形,所以回收机制会有点特殊。

闭包
    所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
    这个定义十分的难以理解,远远的丢至一边,还是用简单的话解释一遍:多层嵌套的函数中,内层的函数能够访问包含它(或是它的上级)的函数的所有变量,同时能够通过回调使得其他作用域也可以使用这些变量。其实这一点就是作用链域的体现,这种特定的变量访问的方式我们就理解为Javascript的闭包特性。


匿名函数:
    简单来讲,一句话:没有函数名的函数。
var add = function(x,y){return x+y;}

    上句中右边就是一个匿名函数。同样,这是另一种定义方式。
(function(x,y){
alert(x+y);
})(3,5);

匿名函数与闭包的区别:由于见到匿名方式的闭包比较多,因此很多人将匿名函数和闭包理解为一个概念,其实要判别一个匿名函数是不是闭包,关键就是看是否通过回调将该函数所属函数中的变量传递给了其他的作用域。

顺便提一个《Javascript高级程序设计》中的闭包的一个例子,对于初学者来说可能相对较难理解(我是用了非常久才想明白的):
function createFunctions(){
var result = new Array();
for(var i=0;i<10;i++){
result[i] = function(){
return i;
}
}
return result;
}
    闭包内是对变量的引用,而非变量值的副本,也就是说result数组的每一项的值都是对变量i的引用,仅仅只是相当于一个指针,当i的值改变时,自然result的每一项的值也就随之改变,该例子中循环完之后i为10,所以每一项都是10。(其实还是比较好理解的哈,我当初不能理解【就是看了说明还是没能理解】的原因是没有把return
后的 i 当成是引用,而是将其当成值赋给了result数组...)
    所以,理解之后就很好改了:
function createFunctions(){
var result = new Array();
for(var i=0;i<10;i++){
result[i] = (function(num){
return num;
})(i);
}
return result;
};
 闭包内如何赋值给全局变量:
    这是今天最初的目标,顺便借这个机会,将这些都整理一遍,加深理解。最后解答一下这个简单问题,直接上例子:
<div id="info">
<ul></ul>
</div> function info(){
var strArr = [];
var data = [
{
"name":"Anny",
"age":"21",
"tel":"333333"
},
{
"name":"Bob",
"age":"33",
"tel":"232223"
},
{
"name":"Tom",
"age":"25",
"tel":"53344"
}
]
for(var i=0;i<data.length;i++){
strArr[i] = (function(obj){
return "姓名:"+obj.name+" 年龄:"+obj.age+" 电话:"+obj.tel;
})(data[i]);
}
return strArr;
}
var strArr = info();
$("#info ul").html("<li>"+strArr[0]+"</li><li>"+strArr[1]+"</li><li>"+strArr[2]+"</li>");

Javascript中闭包的个人理解的更多相关文章

  1. 在Javascript中闭包(Closure)

    在Javascript中闭包(Closure) 什么是闭包 “官方”的解释是:所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. ...

  2. javascript中闭包最简单的简绍

    javascript中闭包是什么 JavaScript 变量可以是局部变量或全局变量.私有变量可以用到闭包.闭包就是将函数内部和函数外部连接起来的一座桥梁. 函数的闭包使用场景:比如我们想要一个函数来 ...

  3. 在JavaScript中闭包的作用和简单的用法

    在JavaScript中闭包的作用和简单的用法 一.闭包的简介 作用域链:在js中只有函数有作用域的概念,由于函数内能访问函数外部的数据,而函数外部不能访问函数内部的数据,由上述形成一种作用域访问的链 ...

  4. 关于javascript中闭包的理解

    闭包就是能够读取其他函数内部变量的函数. 在javascript中,只有函数内部的子函数可以读取局部变量,因此,我理解闭包就是定义在一个函数内部的函数. 例子: var f1 = function() ...

  5. 对JavaScript中闭包的理解

    在前端开发中闭包是一个很重要的知识点,是面试中一定会被问到的内容.之前我对闭包的理解主要是"通过闭包可以在函数外部能访问到函数内部的变量",对闭包运用的也很少,甚至自己写过闭包自己 ...

  6. javascript中闭包与作用域的理解

    很多js的框架与插件编写都用到了闭包,所以,阅读和掌握闭包很有必要.最近学习vue框架时,经常会猜想很多功能的native js实现,很多都应用到了闭包,闭包除了目前已知的一些特性,如:可以保持局部变 ...

  7. 转:对JavaScript中闭包的理解

    关于 const     let      var  总结: 建议使用 let  ,而不使用var,如果要声明常量,则用const. ES6(ES2015)出现之前,JavaScript中声明变量只有 ...

  8. JavaScript中闭包之浅析解读

    JavaScript中的闭包真心是一个老生常谈的问题了,最近面试也是一直问到,我自己的表述能力又不能完全支撑起来,真是抓狂.在回来的路上,我突然想到了一个很简单的事情,其实我们在做项目时候,其实就经常 ...

  9. Javascript中闭包问题(转载)

    学习Javascript闭包(Closure)   作者: 阮一峰 日期: 2009年8月30日 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现 ...

随机推荐

  1. 如何创建JAR文件?如何运行.jar形式的Java程序?

    一.如何创建JAR文件? .jar是用来压缩档案或者解压档案的文件格式,其特点是具有无损压缩的功能.想知道如何创建这种程序?请访问 http://www.cnblogs.com/yjmyzz/p/ex ...

  2. 让 webpack 加载 Source Map

    在浏览器中运行的 JavaScript 代码都是编译器输出的代码,这些代码的可读性很差.如果在开发过程中遇到一个不知道原因的 Bug,则你可能需要通过断点调试去找出问题. 在编译器输出的代码上进行断点 ...

  3. Python读取文件文件夹并检索

    import os import os.path f=open("Shouldlist.txt") ShouldList=[] while 1: line =f.readline( ...

  4. 已经mock类中引用的其它service类,但是在invoke私有方法的时候,该service类是空值

    错误原因:没有在开始测试用例的时候,初始化类的所有注解方法. 解决方法: 使用mock方法创建mock对象时,需要在测试用例执行前执行以下代码.通常, 这句代码可以放在测试基类或者@Before 中. ...

  5. protobuf编译安装

    为什么选择protobuf,而不选择thift和avro,原因大概几点吧,网上对比的文章很多,我主要关注以下几点 1.protobuf序列化性能最好,序列化后字节数最少. 2.protobuf是单纯的 ...

  6. ssh key 免密码登陆服务器,批量分发管理以及挂载远程目录的sshfs

    ssh key 免密码登陆服务器,批量分发管理以及挂载远程目录的sshfs 第一部分:使用ssh key 实现服务器间的免密码交互登陆 步骤1: 安装openssh-clients [root@001 ...

  7. js判断对象的属性是原型的还是实例的

    一些情况下,我们需要知道对象的属性是原型的还是实例的,如果看代码的话比较繁琐,下面讲解下如何可以直接判断 1.hasOwnProperty()函数用于指示一个对象自身(不包括原型链)是否具有指定名称的 ...

  8. 解决ajax跨域问题的多种方法

    //第一种方法使用jsonp的方式 <script type="text/javascript" src="http://www.youxiaju.com/js/j ...

  9. JavaScript提高:002:ASP.NET使用easy UI实现tab效果

    近期在做ASP.NET项目中,须要实现一个tab页控件. 发现asp.net控件中没找到现成的. 一般的实现都须要js和div配合.于是就用到了easyui里面的. 使用也非常easy.将easyui ...

  10. saltstack之定时管理

    1.设置定时任务 /srv/salt/cron/ntpdate.sls /usr/sbin/ntpdate 10.31.10.3; /sbin/hwclock -w: cron.present: - ...