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. iOS应用程序开发之内购

    内购简介 配置iTunes Connect iOS客户端开发工作 一.内购简介 1⃣️通过苹果应用程序商店有三种主要赚钱的方式: –直接收费(与国内大部分用户的消费习惯相悖,如果直接收费,不要设置为6 ...

  2. 本地文件上传到linux

    首先下载插件,输入下面命令: yum -y install lrzsz 然后输入rz选择上传文件: rz 如果rz命令不好使的话,就输入: rz -be

  3. HTML5 2D平台游戏开发#10Wall Jump

    这个术语不知道怎么翻译比较贴切,但并不妨碍对字面意思的理解,大概就是飞檐走壁.比如: 这是游戏<忍者龙剑传>中的场景,玩家可以通过操纵角色在墙面上移动并跳跃. 首先需要实现角色抓墙这一动作 ...

  4. Sqlserver建立Oracle的鏈接服務器

    --建立数据库链接服务器 EXEC sp_addlinkedserver @server =N'TestOracle', --要创建的链接服务器别名 @srvproduct=N'Oracle', -- ...

  5. websocket通讯协议(10版本)简介

    前言: 工作中用到了websocket 协议10版本的,英文的协议请看这里: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotoc ...

  6. mac上搭建docker镜像私服

    1.创建私服容器 docker run -d -e SETTINGS_FLAVOR=dev -e STORAGE_PATH=/tmp/registry -v /opt/data/registry:/t ...

  7. Currency Exchange - poj 1860

    Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 22111   Accepted: 7986 Description Seve ...

  8. MIC中offload语法总结

    MIC中offload的用法如下: #pragma offload specifier [,specifier...]specifier可以填入的选项为:target 例:taget(mic:0)if ...

  9. 刨根问底 HTTP 和 WebSocket 协议(下)

    上篇介绍了HTTP1.1协议的基本内容,这篇文章将继续分析WebSocket协议,然后对这两个进行简单的比较. WebSocket WebSocket协议还很年轻,RFC文档相比HTTP的发布时间也很 ...

  10. oracle操作小计

    1.查询oracle的连接数 select count(*) from v$session; 2.查询oracle的并发连接数 select count(*) from v$session where ...