对javascript闭包的理解
在 JavaScript 中,闭包是一个让人很难弄懂的概念。ECMAScript 中给闭包的定义是:闭包,指的是词法表示包括不被计算的变量的函数,也就是说,函数可以使用函数之外定义的变量。
是不是看完这个定义感觉更加懵逼了?别急,我们来分析一下。
- 闭包是一个函数
- 闭包可以使用在它外面定义的变量
- 闭包存在定义该变量的作用域中
好像有点清晰了,但是使用在它外面定义的变量是什么意思,我们先来看看变量作用域。
var func = function(){var a = 'xiaxiaoxian';console.log(a); // xiaxiaoxian
}
func();
console.log(a); // Uncaught ReferenceError: a is not defined
变量生存周期
全局变量,生命周期是永久的。局部变量,当定义该变量的函数调用结束时,该变量就会被垃圾回收机制回收而销毁。再次调用该函数时又会重新定义了一个新变量。
var func = function(){var a = 'xiaxiaoxian';console.log(a);
}
func();
a 为局部变量,在 func 调用完之后,a 就会被销毁了。
var func = function(){var a = 'xiaxiaoxian';var func1 = function(){a += ' a';console.log(a);}return func1;
}
var func2 = func();
func2(); // xiaxiaoxian a
func2(); // xiaxiaoxian a a
func2(); // xiaxiaoxian a a a
可以看出,在第一次调用完 func2 之后,func 中的变量 a 变成 ‘xiaxiaoxian a’,而没有被销毁。因为此时 func1 形成了一个闭包,导致了 a 的生命周期延续了。
这下子闭包就比较明朗了。
- 闭包是一个函数,比如上面的 func1 函数
- 闭包使用其他函数定义的变量,使其不被销毁。比如上面 func1 调用了变量 a
- 闭包存在定义该变量的作用域中,变量 a 存在 func 的作用域中,那么 func1 也必然存在这个作用域中。
现在可以说,满足这三个条件的就是闭包了。
下面我们通过一个简单而又经典的例子来进一步熟悉闭包。
for (var i = 0; i < 4; i++) {setTimeout(function () {console.log(i)}, 0)
}
我们可能会简单的以为控制台会打印出 0 1 2 3,可事实却打印出了 4 4 4 4,这又是为什么呢?我们发现,setTimeout 函数时异步的,等到函数执行时,for循环已经结束了,此时的 i 的值为 4,所以 function() { console.log(i) } 去找变量 i,只能拿到 4。
我们想起上一个例子中,闭包使 a 变量的值被保存起来了,那么这里我们也可以用闭包把 0 1 2 3 保存起来。
for (var i = 0; i < 4; i++) {(function (i) { // i是受保护的变量setTimeout(function () {console.log(i)}, 0)})(i)
}
当 i=0 时,把 0 作为参数传进匿名函数中,此时 function(i){} 此匿名函数中的 i 的值为 0,等到 setTimeout 执行时顺着外层去找 i,这时就能拿到 0。如此循环,就能拿到想要的 0 1 2 3。
内存管理
在闭包中调用局部变量,会导致这个局部变量无法及时被销毁,相当于全局变量一样会一直占用着内存。如果需要回收这些变量占用的内存,可以手动将变量设置为null。
然而在使用闭包的过程中,比较容易形成 JavaScript 对象和 DOM 对象的循环引用,就有可能造成内存泄露。这是因为浏览器的垃圾回收机制中,如果两个对象之间形成了循环引用,那么它们都无法被回收。
function func() {var test = document.getElementById('test');test.onclick = function () {console.log('hello world');}
}
在上面例子中,func 函数中用匿名函数创建了一个闭包。变量 test 是 JavaScript 对象,引用了 id 为 test 的 DOM 对象,DOM 对象的 onclick 属性又引用了闭包,而闭包又可以调用 test ,因而形成了循环引用,导致两个对象都无法被回收。要解决这个问题,只需要把循环引用中的变量设为 null 即可。
function func() {var test = document.getElementById('test');test.onclick = function () {console.log('hello world');}test = null;
}
如果在 func 函数中不使用匿名函数创建闭包,而是通过引用一个外部函数,也不会出现循环引用的问题。
function func() {var test = document.getElementById('test');test.onclick = funcTest;
}
function funcTest(){console.log('hello world');
}
对javascript闭包的理解相关推荐
- Javascript闭包简单理解
Javascript闭包简单理解 原文:Javascript闭包简单理解 提到闭包,想必大家都早有耳闻,下面说下我的简单理解. 说实话平时工作中实际手动写闭包的场景并不多,但是项目中用到的第三方框架和 ...
- 关于Javascript闭包的理解
一.什么是闭包? "官方"的解释是:所谓"闭包",指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 相 ...
- javascript闭包的理解
javascript闭包是javascript的难点,很多人对js闭包不是很理解,我对js闭包一开始也是云里雾里,我刚刚进兴安得力的时候,做的转正试题中就有一个对闭包理解的题目.如何理解javascr ...
- JavaScript闭包函数理解
JavaScript闭包 一.变量的作用域: 要理解闭包,首先必须理解JavaScript特殊的变量作用域. 变量作用域无非就是两种:全局变量 和 局部变量. JavaScrip ...
- 关于Javascript闭包的理解(二)
先看看闭包的科学的定义:闭包是可以包含自由(未绑定)变量的代码块:这些变量不是在这个代码块或者任何全局上下文中定义的,而是在定义代码块的环境中定义."闭包" 一词来源于以下两者的结 ...
- 浅谈对JavaScript闭包的理解
首先我们先来看一段代码 从上面的代码可以看出js都有一个特性特性,局部方法可以访问外部父类方法的属性,也就是说,子类或子方法可以访问父类的资源. 我们再来看一段代码 为什么我们打印出来的是undefi ...
- 全面理解Javascript闭包和闭包的几种写法及用途【转】
一.什么是闭包和闭包的几种写法和用法 1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点: 1. ...
- 全面理解Javascript闭包和闭包的几种写法及用途
一.什么是闭包和闭包的几种写法和用法 1.什么是闭包 闭包,官方对闭包的解释是:一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分.闭包的特点: 1. ...
- 让你分分钟理解 JavaScript 闭包
原文:https://www.cnblogs.com/onepixel/p/5062456.html 让你分分钟理解 JavaScript 闭包 闭包,是 Javascript 比较重要的一个概念,对 ...
最新文章
- 独家 | 使EfficientNet更有效率的三种方法(附链接)
- canopen服务器协议,CANopen
- mysql主键创建非聚集索引_什么是聚集索引,非聚集索引,索引覆盖,回表,索引下推...
- 10_Android中通过HttpUrlConnection访问网络,Handler和多线程使用,读取网络html代码并显示在界面上,ScrollView组件的使用
- Spring.Net学习笔记(2)-依赖注入
- jzoj_3385_黑魔法师之门
- 【POJ - 2594】Treasure Exploration(floyd传递闭包 + 最小路径覆盖,图论)
- python读取print输出的内容_Python文件中将print的输出内容重定向到变量中
- Javascript的数组对象
- 项目经理:赢得项目不是终点而是起点
- JavaScript:如何将消息打印到错误控制台?
- 对Javascript异步执行的理解
- 21天学通java6 pdf_21天学通Java(第6版) PDF_IT教程网
- APS高级计划排程系统和生产排产系统
- 【2020年高被引学者】 汤继良 密歇根州立大学
- 网页排版布局常见问题有哪些?
- Android源码分析(十三)----SystemUI下拉状态栏如何添加快捷开关
- Android转接电话到iPhone,Android迁移数据到iPhone
- 三极管的上拉下拉电阻的选取
- IOS7 隐藏状态栏 (电池栏)
热门文章
- 松下服务器分频器输出信号与,基础资料松下PANASONIC伺服驱动器MADHT1507E
- matlab温度数据怎么滤波_卡尔曼滤波算法思想理解 Kalman filter 第一篇
- mysql编辑工具wf_轻松构建自定义WF设计器
- win10系统配置apache 2.4的虚拟主机以及查看 apache的版本
- 培养产品思维,每个人都应该是产品经理
- 【深度学习】CNN神经网络应用(用于亚洲大黄蜂分类)
- Android移动开发之【Android实战项目】DAY10-App端耗流量场景问题及减少消耗办法
- 习题2.4 递增的整数序列链表的插入 (15 分)
- 计算机网络高分笔记视频,计算机网络高分笔记(整理).pdf
- 领计算机二级证材料,计算机二级证书怎么领