js之认识闭包
本文采用5W1H分析法来看一下闭包。
一、why-----从为什么要引入闭包先来了解一下闭包。
讨论为什么要引入闭包就要先讨论一下js中的作用域链及垃圾回收机制。
熟悉js语言的人都知道js中有作用域的概念和垃圾回收机制。那么我们首先来看一下js中的作用域链
- 作用域链:
js中的变量执行环境分为全局执行环境和局部执行环境。当代码在执行时会创建变量对象的一个作用域链。而作用域链简单来说,就是函数在定义的时候创建的上下文执行环境,用于在标识符解析中变量查找。作用域链的前端始终都是当前执行代码所在环境的变量对象即函数自身的本地变量,作用域链的下一个变量对象来自包含环境即父级函数,而在下一个变量对象则来自下一个包含环境,然后一直延续到全局执行环境;全局执行环境的变量对象始终是作用域链的最后一个对象。js中标识符解析就是沿着作用域链一级一级地搜索标识符的过程;搜索过程从作用域链的前端开始逐级向上搜索,直到找到标识符为止。
作用域链只能从下往上查找而不能从上往下查找,举例来说函数内部可以访问到全局变量,而在函数外部不能访问函数内部变量。如下代码:
var n=999;
function f1(){
alert(n);
}
f1(); //
代码中n为全局变量,而在函数内部可以直接访问到。再看以下代码:
function f1(){
var n=999;
}
alert(n); // 会报错 n is not defined
当在函数外部访问内部变量时会报错。了解了作用域链再来看一下js垃圾回收机制。
2.js中垃圾回收机制:
javascript时一门具有自动垃圾回收机制的语言。一般来说,一个函数在执行开始的时候,会给其中定义的局部变量划分内存空间以便存储他们的值,然后在函数中使用变量,等到函数执行完毕返回了,局部变量就没有存在的必要了,这些变量就被认为是无用的了;因此释放他们的内存供将来使用,下次再执行此函数的时候,所有的变量又回到最初的状态,重新赋值使用。由于作用域链和垃圾回收机制的限制,若需要在函数外部访问函数内部的变量则访问不到。若要想在函数外部访问函数内部的变量怎么访问呢?此时闭包就华丽登场了(*^_^*)。
二、what-----什么是闭包呢从概念来理解
《javascript高级程序设计第三版》中是这样定义闭包的“闭包是指有权访问另一个函数作用域中的变量的函数”。所有的函数都可以说是闭包。在我理解,简单来说就是在一个函数内部嵌套一个函数,内部函数可以引用外部函数的参数和变量,参数和变量不会被回收,使局部变量能够在全局中访问到,暴露局部变量能够让他的上一层环境访问到。闭包由函数和创建该函数的执行环境构成。当在函数内部嵌套另外一个函数时,并且外部函数将嵌套的函数对象作为返回值返回就是闭包的一种。如下代码实例:
function aaa() {
var a=1;
function bbb(){
a++;
alert(a);
}
return bbb;
} var c=aaa();
c();//2
内部函数bbb可以访问到外部函数中的a变量。当外部函数执行完后,由于内部函数引用了外部函数的变量,因此内部函数的作用域包含了外部函数的活动对象,当外部函数被调用返回后其执行环境被销毁,但内部函数的作用域链依然存在,因其内部函数还未被销毁所以其外部函数的活动对象仍然在内存中,如在bbb中访问a变量依然可以访问到。等其内部函数执行完后作用域链被销毁,释放变量内存。了解了闭包的概念,再来看一下闭包的应用场景。
三、when------什么时候使用闭包?
当希望一个变量长期驻扎在内存中时,此时使用闭包可以使函数执行完后其活动对象仍然在内存中。
四、where----闭包应用在哪?
闭包好处:1、避免全局变量的污染
2、可以模仿块级作用域
3、私有成员的存在
1、闭包可以用来模仿块级作用域。
js中本身没有块级作用域的概念,而使用闭包可以用来模仿块级作用域。
function outputNumbers(count){
(function(){
for(var i=0;i<count;i++){
alert(i);
}
})();
alert(i);//报错 i is not defined
}
在for循环外部插入一个私有作用域,变量i只能在循环中使用,使用后即被销毁。所以在私有作用域外部访问不到。
2、在循环中直接找到对应的索引。
若页面中有多个li标签,而需要给每个标签添加一个事件,则可以这样做:
for(var i=0;i<aLi.length;i++){
(function(i){
aLi[i].onclick=function(){
alert(i);
}
})(i);
}
如果不使用闭包的话,那么弹出的i为aLi.length的值。
for(var i=0;i<6;i++){
aLi[i].onclick=function(){
alert(i);//
}
}
3、用闭包模拟私有方法:
js中本身没有私有成员的概念,所有对象属性都是公有的。闭包可以用来创建私有变量。如下代码:
var aaa = (function(){
var a = 1;
function bbb(){
a++;
alert(a);
}
function ccc(){
a++;
alert(a);
}
return {
b:bbb, //json结构
c:ccc
}
})();
aaa.b(); //
aaa.c()
4、模块化代码,避免全局变量的污染:
var abc = (function(){ //abc为外部匿名函数的返回值
var a = 1;
return function(){
a++;
alert(a);
}
})();
abc(); //2 调用一次abc函数,其实是调用里面内部函数的返回值
abc(); //
接下来再来看一下闭包的缺点:闭包会使变量始终保存在内存中,如果不当使用会增大内存消耗。还有由于IE
的js
对象和DOM
对象使用不同的垃圾收集方法,因此闭包在IE
中会导致内存泄露问题,也就是无法销毁驻留在内存中的元素。只有关闭浏览器时才会释放内存。如下代码:
function fn(){
var oDiv = document.getElementById('div1');//oDiv用完之后一直驻留在内存中
oDiv.onclick = function () {
alert(oDiv.id);//这里用oDiv导致内存泄露
};
}
fn();
//最后应将oDiv解除引用来避免内存泄露
function fn(){
var oDiv = document.getElementById('div1');
oDiv.onclick = function () {
alert(oDiv.id);
};
oDiv = null;
}
由于oDiv.onclick中引用了oDiv.id,互相引用时存在内存泄漏,因此需手动解除引用来避免内存泄漏。
js之认识闭包的更多相关文章
- 详解js中的闭包
前言 在js中,闭包是一个很重要又相当不容易完全理解的要点,网上关于讲解闭包的文章非常多,但是并不是非常容易读懂,在这里以<javascript高级程序设计>里面的理论为基础.用拆分的方式 ...
- js中的闭包之我理解
闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的 ...
- Js(javaScript)的闭包原理
问题?什么是js(javaScript)的闭包原理,有什么作用? 一.定义 官方解释:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 小编 ...
- 浅谈JS中的闭包
浅谈JS中的闭包 在介绍闭包之前,我先介绍点JS的基础知识,下面的基础知识会充分的帮助你理解闭包.那么接下来先看下变量的作用域. 变量的作用域 变量共有两种,一种为全局变量,一种为局部变量.那么全局变 ...
- js中的“闭包”
js中的“闭包” 姓名:闭包 官方概念:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. ( ⊙o⊙ )!!!这个也太尼玛官方了撒,作为菜鸟的 ...
- JS中的闭包(closure)
JS中的闭包(closure) 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现.下面就是我的学习笔记,对于Javascript初学者应该是很有用 ...
- Js中的闭包原理
要了解清楚js中的闭包制机,那么得先了解全局执行环境.块级执行环境.函数执行环境.变量对象.环境栈.作用域链.摧毁执行环境. 全局执行环境 全局执行环境指的是最外层的执行环境.在web中全局执行环境被 ...
- js中的闭包理解一
闭包是一个比较抽象的概念,尤其是对js新手来说.书上的解释实在是比较晦涩,对我来说也是一样. 但是他也是js能力提升中无法绕过的一环,几乎每次面试必问的问题,因为在回答的时候.你的答案的深度,对术语的 ...
- JS基础学习——闭包
JS基础学习--闭包 什么是闭包 闭包的定义如下,它的意思是闭包使得函数可以记住和访问它的词法范围,即使函数是在它声明的词法范围外执行.更简单来讲,函数为了自己能够正确执行,它对自己的词法范围产生闭包 ...
- JS面向对象之闭包
闭包 闭包的概念 闭包的含义就是闭合,简单来说就是一个具有封闭功能的结构 闭包就是具有封闭的对外不公开的,包裹结构或空间 在 js 中的闭包 在 js 中函数可以构成闭包 函数是一个代码结构的封闭结构 ...
随机推荐
- [LeetCode] Remove Duplicates from Sorted List II 移除有序链表中的重复项之二
Given a sorted linked list, delete all nodes that have duplicate numbers, leaving only distinct numb ...
- VS2015 使用及插件推荐
环境搭建与插件推荐 Cpp in Win10 x64 vs2015 + Resharper/Visual Assist X vs2015Pro: Download or see BaiDu 中文专 ...
- IT培训行业揭秘(一)
最近一个多月来,身边有很多朋友问我,我家孩子明年就要大学毕业了,现在工作还没有着落,最近孩子回家经常和我说,他们学校最近来了很多IT培训班,让同学们参加培训,然后各个培训班动辄拿出往届他们的培训学生赚 ...
- Keepalived的全局配置
Keepalived的全局配置 默认配置文件如下: ! Configuration File for keepalived global_defs { notification_email { aca ...
- C#图像处理笔记
1.灰度拉伸 灰度拉伸又叫对比度拉伸,它是最基本的一种灰度变换,使用的是最简单的分段线性变换函数,它的主要思想是提高图像处理时灰度级的动态范围.
- java 中正则表达式匹配
String str = "#a#,#b#"; String reg="\\#+[^\\#]+\\#+"; Pattern p=Pattern.compile( ...
- 关于input的file框onchange事件触发一次失效的新的解决方法
在google了众多方法后,网上有这么几种方法: 1.替换掉原来的input框 2.remove原来的input框,然后在添加进新的一样的input框 但是不知道为什么非常不幸的是,怎么弄我都弄不出. ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
- javadoc
Oracle官方javadoc说明 Generates HTML pages of API documentation from Java source files. http://docs.orac ...
- 【poj3071】 Football
http://poj.org/problem?id=3071 (题目链接) 题意 ${2^n}$个队伍打淘汰赛,输的被淘汰.第1个队打第2个队,第3个队打第4个队······给出第i个队伍打赢第j个队 ...