Javascript Closure
为什么知道闭包很重要?
闭包是JS语言的难点也是其一大特色,很多初学者甚至从业多年的开发者也很难弄清楚这个概念。弄明白这个概念十分重要,因为不但是对学习JS语言的一个大提升,在编写高级应用时候经常要用到,同时也是很多面试题目中经常会考到的问题。
闭包的“官方”解释:
所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
想必上述解释大部分人看起来都像是天书,要了解闭包首先我们还需要知道JS语言的作用域这个概念。
变量的作用域
函数内部可以直接读取全局变量。
var n=7; function f1 () { alert(n); } f1(); // 7
在函数外部自然无法读取函数内的局部变量。
function f1 () { var n=7; } alert(n); // error
这样牵扯出来一个问题:如何访问函数内部的变量呢 ?
我们先来看下面一个例子:
function f1() { var n = 7; function f2 (){ alert(n); } return f2; } var result = f1(); result();
这里就形成了闭包,由此我们可以给闭包一个新的解释。
闭包的“通俗”解释:
闭包就是能够读取其他函数内部变量的函数,其本质就是就是将函数内部和函数外部连接起来的一座桥梁。
(闭包是由函式和与其相关的参照环境组合而成的实体。即便在函数内部定义了函数,如果没有引用父函数作用域的变量,也照样可以不是闭包。函数和环境,缺一不可,这才是闭包。)
再看一个稍微复杂一点的例子:
var foo = ( function () { var secret = 'secret'; return { get_secret: function () { return secret; }, new_secret: function (new_secret) { secret = new_secret; } }; }() ); foo.get_secret (); // 得到 ‘secret' foo.secret; // Type error,访问不能 foo.new_secret ('a new secret'); // 通过函数接口,我们访问并修改了 secret 变量 foo.get_secret (); // 得到 'a new secret'
引用 Douglas Crockford [1] :
之所以可能通过这种方式在 JavaScript 种实现公有,私有,特权变量正是因为闭包,闭包是指在 JavaScript 中,内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
闭包主要应用场合主要是为了:设计私有的方法和变量。
function foo(x) { var tmp = 3; return function (y) { alert(x + y + (++tmp)); } } var bar = foo(2); // bar 现在是一个闭包 bar(10);
闭包特点
闭包会把函数中的变量都被保存在内存中。
注意点
1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除
2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。
参考资源
ECMA-262-3 in detail. Chapter 6. Closures.
[1] how do JavaScript closures work
[2] 学习Javascript闭包(Closure)
[3] 理解Javascript的闭包
[4] JavaScript:闭包和引用
[5] Private Members in JavaScript
该篇文章是公司技术分享会的演讲稿文字整理
相关推荐
} 这里的闭包是f1,封闭了一个变量n和一个函数f2。 我们先无视nAdd,尽量保持原貌重写一下这个函数。 代码如下: function f1(){ var n = 999; var f2 = function(){ alert(n); }; return f2; } var result ...
浅谈JavaScript for循环闭包 在JavaScript中,for循环和闭包是两个非常重要的概念。本文将对JavaScript for循环和闭包进行浅谈,并提供六种解决方案来解决for循环中的闭包问题。 首先,让我们来看一个例子。我们有...
在JavaScript编程中,闭包是一个非常重要的概念,它的特性使得函数可以访问到外部函数作用域中的变量。然而,闭包如果使用不当,非常容易引起...通过以上措施,可以最大限度地减少JavaScript闭包所带来的内存泄漏问题。
项目经过测试均可完美运行! 环境说明: 开发语言:java jdk:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse
项目经过测试均可完美运行! 环境说明: 开发语言:java jdk:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse
基于java的网吧管理系统答辩PPT.pptx
基于java的基于SSM架构的网上书城系统答辩PPT.pptx
tornado-6.1-cp37-cp37m-win32.whl
c语言气泡排序、插入排序、选择排序、快速排序、希尔排序、堆排序、合并排序_SortAlgorithm.zip
Keyboard Maestro 11.0.3_macwk.dmg
基于微信小程序的鲜花销售微信小程序答辩PPT.pptx
项目经过测试均可完美运行! 环境说明: 开发语言:java jdk:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse
tornado-6.2b1-cp39-cp39-musllinux_1_1_x86_64.whl
项目经过测试均可完美运行! 环境说明: 开发语言:java jdk:jdk1.8 数据库:mysql 5.7+ 数据库工具:Navicat11+ 管理工具:maven 开发工具:idea/eclipse
tornado-6.1b2-cp38-cp38-manylinux2014_aarch64.whl
基于java的土家风景文化管理平台答辩PPT.pptx
jira安装包
基于java的机场网上订票系统答辩PPT.pptx
小区物业管理系统 SSM毕业设计 附带论文 启动教程:https://www.bilibili.com/video/BV1GK1iYyE2B