学习Javascript闭包(Closure)
感觉讲的挺好的,考虑到之前被朴灵喷的很惨,所以开始怀疑博文中的讲解是否正确。
博文部分观点:
1. 我的理解是,闭包就是能够读取其他函数内部变量的函数。
2.由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。
3.闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
回复内容:
某些說法的確不嚴謹,但也沒必要噴。比如:
函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!不使用 var 等於沒有聲明變量,而是相當於訪問了 window 的屬性。
和在 window 下聲明變量的區別在於,訪問 window 的屬性創建的變量可以 delete,在全局作用域下直接聲明的變量不可以 delete。
window.b = "hi";
b; // "hi"
delete b; // true
b; // ReferenceError: b is not defined
(function(){c = "hi"}());
c; // "hi"
delete c; // true
c; // ReferenceError: c is not defined
var a = "hi";
a; // "hi"
delete a; // false
a; // "hi"
以 “某些說法的確不嚴謹,但也沒必要噴。” 开头的匿名回答是对的。关于闭包的概念,其实就是来自函数式语言。
var a = function () {
var test = {};
setTimeout(function () {
console.log(test);
}, 1000);
}
阮一峰的文章是他的学习笔记,并不保证全部正确,因为只是他的理解,而且这篇文章是他09年时写的,可能那时候他的水平比现在还差一些。不过他文章的含金量还是比较高的,同时因为是他的学习笔记,所以我们读起来也通俗易懂。很多初学者可以从阮一峰的文章向高水平进阶,但是通俗易懂的东西一般会存在不严谨的情况。严谨的文章非常好,但是不利于初学者理解。为什么这么说呢,严谨的概念会包含很多对初学者来说十分模糊的专业术语,比如上面答主cosx所提到的:閉包是由函式和與其相關的參照環境組合而成的實體。(原句可能是:A "closure" is an expression (typically a function) that can have free variables together with an environment that binds those variables (that "closes" the expression).)如果是初学者,我相信一看到函式、相关环境等字眼,则直接懵逼。
但是阮一峰说:闭包就是能够读取其他函数内部变量的函数。这么解释,只要动动脑,应该可以大概理解闭包是什么东西了。即便这句话很不严谨。
所以说阮一峰的文章依然值得看,他的文章可以把你带入一个领域,但是想要正确的认识这个领域,你依然需要去看书,这也是网络文章与实体书的区别。
----------------------------------------------
想要彻底正确的理解闭包,还是要看cosx、朴灵的回答,但是要攒够基础知识。 闭包就是在函数中使用的未在函数中定义的但在函数所处上下文有效的变量(标识符)与函数本体的集合。 还是严谨一点比较好 闭包确实是js最难理解的东西了,闭包的本质可以说是作用域链形成的
要理解闭包,必须要理解这几个概念
1.词法作用域
2.执行上下文
3.活动对象
4.scope属性
假设如下代码
function A(arg1){
var v1=1;
var b=function B(){ //执行到这一行定义了函数B,用表达式避免变量提升问题
}
}
A();
一个函数B在定义(声明)时,它在代码树上的上一层函数A此时正处于运行状态(执行上下文指向函数A),此时函数B会生成一个scope属性(函数本质也是对象,可以定义属性),B.scope是一个数组,但是通过代码是访问不到的,通过chome调试面板可以看到,留心的同学可以发现,push了A的活动对象(如果A有上一层函数,会依次push进去),此时B.scope=[{v1:1}],当前函数的活动对象包含了一个函数体内所有var声明的变量,在函数B内部查找变量时优先查找B的活动对象中的变量,如果没有,则遍历scope属性数组中的父级函数活动对象。
因为只有在运行时的代码才能声明函数,每一个函数在声明时,父级函数必然处于执行状态,递归思考一下,可知作用域链完全由函数编写时的嵌套顺序所决定,这就是词法作用域的含义,看一个函数的作用域,只要静态分析代码树的结构就行了。
所谓的作用域链,其实就是隐含的scope属性一级级的向上引用上一层函数的变量对象,变量对象的查找过程,原理上和对象的属性通过__proto__原型链查找过程差不多。 闭包就是打入敌人内部的间谍,通过他你可以接触敌人对外封锁的信息。 再提一些个人认为有误导性的地方!
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
搞的好像其他面向对象的语言不能似的。另一方面,在函数外部自然无法读取函数内的局部变量。
根本没有提到关键,为什么不能读取内部变量?函数在执行完后会销毁其内部环境这个就没提及。第六个思考题:
如果你能理解下面两段代码的运行结果,应该就算理解闭包的运行机制了。
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
什么是闭包?闭包并不是什么新奇的概念,它早在高级语言开始发展的年代就产生了。闭包(Closure)是词法闭包(Lexical Closure)的简称。对闭包的具体定义有很多种说法,这些说法大体可以分为两类:
- 一种说法认为闭包是符合一定条件的函数,比如参考资源中这样定义闭包:闭包是在其词法上下文中引用了自由变量(注1)的函数。
- 另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。比如参考资源中就有这样的的定义:在实现深约束(注2)时,需要创建一个能显式表示引用环境的东西,并将它与相关的子程序捆绑在一起,这样捆绑起来的整体被称为闭包。
这两种定义在某种意义上是对立的,一个认为闭包是函数,另一个认为闭包是函数和引用环境组成的整体。虽然有些咬文嚼字,但可以肯定第二种说法更确切。闭包只是在形式和表现上像函数,但实际上不是函数。函数是一些可执行的代码,这些代码在函数被定义后就确定了,不会在执行时发生变化,所以一个函数只有一个实例。闭包在运行时可以有多个实例,不同的引用环境和相同的函数组合可以产生不同的实例。所谓引用环境是指在程序执行中的某个点所有处于活跃状态的约束所组成的集合。其中的约束是指一个变量的名字和其所代表的对象之间的联系。那么为什么要把引用环境与函数组合起来呢?这主要是因为在支持嵌套作用域的语言中,有时不能简单直接地确定函数的引用环境。这样的语言一般具有这样的特性:
- 函数是一阶值(First-class value),即函数可以作为另一个函数的返回值或参数,还可以作为一个变量的值。
- 函数可以嵌套定义,即在一个函数内部可以定义另一个函数。
3:永久保存在内存?只是将对象的生命延长到和使用它的函数一致。如果所有使用它的函数都被回收了,这个变量也就回收了。(好吧,在实践中,这属于钻牛角尖了,而且还要看JS引擎如何实现)
闭包在JS中的作用:
隐藏私有变量
将额外参数传递给运行时生成的函数 (因为你生成的函数会被别人调用,比如回调函数,毫无疑问函数的参数个数和次序已定,但你的函数确实需要更多信息)
需要注意的问题:
一个变量进入闭包后,会被复制到堆中,所有对该变量的使用都解析为引用这个堆中的变量。所以,使用这个变量的所有函数都会读取到最新的值,而不是你创建该函数时的值。
其实 专业一点的JS书中都有解释。
![Web大前端开发直播班](http://m.sbmmt.com/img/upload/aroundimg/000/000/071/62566f0ccc0d9487.png)
相关文章推荐
• 完全掌握Python数学相关模块• Python详细解析之多线程爬虫与常见搜索算法• 三种方法使用For循环遍历Python字典(实例详解)• 带你搞懂Python反序列化• 归纳整理Python正则表达式知识点独孤九贱(3)_JavaScript视频教程
javascript是运行在浏览器上的脚本语言,连续多年,被评为全球最受欢迎的编程语言。是前端开发必备三大法器中,最具杀伤力。如果前端开发是降龙十八掌,好么javascript就是第18掌:亢龙有悔。没有它,你的前端生涯是不完整的。《php.cn独孤九贱(3)-JavaScript视频教程》课程特色:php中文网原创幽默段子系列课程,以恶搞,段子为主题风格的php视频教程!轻松的教学风格,简短的教学模式,让同学们在不知不觉中,学会了javascript知识。
JavaScript教程121528次播放
独孤九贱(6)_jQuery视频教程
jQuery是一个快速、简洁的JavaScript框架。设计的宗旨是“write Less,Do More”,即倡导写更少的代码,做更多的事情。它封装JavaScript常用的功能代码,提供一种简便的JavaScript设计模式,优化HTML文档操作、事件处理、动画设计和Ajax交互。 核心特性可以总结为:具有独特的链式语法和短小清晰的多功能接口;具有高效灵活的css选择器,并且可对CSS选择器进行扩展;拥有便捷的插件扩展机制和丰富的插件。兼容各种主流浏览器,如IE 6.0+、FF 1.5+、Safari 2.0+、Opera 9.0+等,是全球最流行的前端开发框架之一。PHP中文网根据最新版本,独家录制jQuery最新视频教程,回馈PHP中文网的新老用户。
jQuery教程100592次播放
传智播客JavaScript面向对象完成贪吃蛇游戏视频教程
《传智播客JavaScript面向对象完成贪吃蛇游戏视频教程》介绍了关于JavaScript面向对象的知识,利用面向对象的编程思想去完成贪吃蛇游戏。
JavaScript教程4390次播放
react+redux(英文版)
React是一个用于构建用户界面的JavaScript库,也是Web应用程序的视图层,Redux对于JavaScript应用而言是一个可预测状态的容器,它是一个应用数据流框架。
React教程3752次播放
JSON与AJAX原理与实战
json是一种独立于编程语言的,通用的轻量级的数据存储与交换格式,基于javascript对象语法书写,非常适合Web开发。Ajax是异步的数据加载技术,可以使用户不离开当前页面获取数据,用户体验极佳,本套课程结合json和ajax技术,实例展示这二个技术的应用场景(涉及的php和mysql知识可暂时忽略)
JavaScript教程2764次播放