在学习闭包之前我们很有必要先了解什么是作用域链

一、作用域链

作用域链是保证对执行环境有权访问的所有变量和函数的有序访问。

这句话其实还是蛮抽象的,但是通过下面一个例子,我们就能清楚的了解到作用域链了。

 var color="blue";
function changeColor(){
var anotherColor="red";
function swapColors(){
var tempColor=anotherColor;
anotherColor=color;
color=tempColor;
//这里面可以访问color、anotherColor和tempColor
}
//这里面可以访问anotherColor和color
}
//这里面只能访问color

以上代码涉及了3个执行环境:全局环境、changeColor()局部环境和swapColor()局部环境。在一个变量环境中只能访问他自己的环境和父执行环境。swapColor()的父执行环境就是changeColor(),而changeColor()的父执行环境就是全局环境。如果还不清楚可以参考下图

在f2()函数的局部环境中能访问自己和比它等级高的,也就是a,b,c,同理f1()函数环境访问b,a,全局环境只能访问c。

我们这时候会发现函数外部是无法访问内部的局部环境的,但是我们想突破作用域链怎么办呢?这时候就有了闭包共享作用域。闭包这个名词就出现了。

二、闭包

闭包在红宝书中的解释就是:有权访问另一个函数作用域中的变量的函数。

下来举一个简单的例子

  function f1(){
var a=1;
return function(){
return a;
}
}
alert(a); /*结果为 a is undefined*/
var task=f1(); /*task就是闭包,有权访问其他函数作用域变量*/
alert(task());/*结果为1*/

下来我们再举一个闭包的例子

 function f1(){
var n=0;
task=function(){ //匿名函数
n+=1;
}
//这部分为闭包
function f2(){
alert(n);
}
return f2 //返回
}
var text=f1();
alert(text());
task();
alert(text()); //结果依次为 0,undefined,1,undefined

text是f2闭包函数,实际上f2()被赋予一个全局变量,f2()始终在内存中,f1()是它的父级函数,所以f1()也始终在内存中,不会被销毁。执行一次task()后,值变为2。至于为什么会出现undefined是因为,undefined是text的返回值,也就是闭包函数无返回值了。

有时候我们想改变其他函数作用域里的变量,这时候就可以用闭包去解决。设置两个额外的函数去访问内部函数。

 var setvalue,getvalue;
(function(){
var n=0;
getvalue=function(){
return n
}
setvalue=function(x){
n=x;
}
})(); //直接调用
alert(getvalue()); //结果为0
setvalue(456);
alert(getvalue());/*结果为456*/

这时候我们发现在外部就可以去改变内部变量值。

下来再举一个利用闭包循环遍历得到数组的值。有两个程序,可以对比一下两个程序的区别

例1:

 function f1(){
var a=[];
var i=0;
for(i=0;i<3;i++){
a[i]=function(){
return i;
}
}
return a;
}
var text=f1();
alert(text[0]());
alert(text[1]());
alert(text[2]()); //结果都为3

因为闭包都指向局部变量i,只是给出了指针链接,对变量的引用,并没有对值作出改变。所以结果都为3

例2:

  function f1(){
function f2(x){ //闭包
return function(){
return x;
}
}
var a=[];
var i=0;
for(i=0;i<3;i++){
a[i]=f2(i);
}
return a;
}
var text=f1();
alert(text[0]()); //结果为1
alert(text[1]());//结果为2
alert(text[2]());//结果为3

利用一个函数参数,用闭包去获取内部变量的值。

程序是这样走的:先判断谁进来--》调用闭包--》闭包返回内部函数参数--》最后再创建数组。

三、闭包的缺点

  这上面几个例子确实体会到了闭包的强大,但是闭包也有明显的缺点,它使函数中的变量都保存在内存中,占用内存,导致页面加载缓慢。所以再退出函数前,将不用的局部变量删除。

四、总结

  以上就是我学习闭包总结的一点小知识。大家互相交流哈 O(∩_∩)O。

  附阮一峰老师对闭包的理解:http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html?20120612141317#comments

  

js学习笔记之作用域链和闭包的更多相关文章

  1. js考察this,作用域链和闭包

    在严格版中的默认的this不再是window,而是undefined. 先看两个例子 example one var num = 20; var obj = { num: 30, fn: (funct ...

  2. JS 学习笔记--9---变量-作用域-内存相关

    JS 中变量和其它语言中变量最大的区别就是,JS 是松散型语言,决定了它只是在某一个特定时间保存某一特定的值的一个名字而已.由于在定义变量的时候不需要显示规定必须保存某种类型的值,故变量的值以及保存的 ...

  3. JS详细图解作用域链与闭包

    JS详细图解作用域链与闭包 攻克闭包难题 初学JavaScript的时候,我在学习闭包上,走了很多弯路.而这次重新回过头来对基础知识进行梳理,要讲清楚闭包,也是一个非常大的挑战. 闭包有多重要?如果你 ...

  4. JS 之作用域链和闭包

    1.JS无块级作用域 <script> function Main(){ if (1==1){ var name = "alex"; } console.log(nam ...

  5. 前端高质量知识(四)-JS详细图解作用域链与闭包

    攻克闭包难题 初学JavaScript的时候,我在学习闭包上,走了很多弯路.而这次重新回过头来对基础知识进行梳理,要讲清楚闭包,也是一个非常大的挑战. 闭包有多重要?如果你是初入前端的朋友,我没有办法 ...

  6. js深入(三)作用域链与闭包

    在之前我们根绝对象的原型说过了js的原型链,那么同样的js 万物皆对象,函数也同样存在这么一个链式的关系,就是函数的作用域链 作用域链 首先先来回顾一下之前讲到的原型链的寻找机制,就是实例会先从本身开 ...

  7. 1--面试总结-js深入理解,对象,原型链,构造函数,执行上下文堆栈,执行上下文,变量对象,活动对象,作用域链,闭包,This

    参考一手资料:http://dmitrysoshnikov.com/ecmascript/javascript-the-core/中文翻译版本:https://zhuanlan.zhihu.com/p ...

  8. js之作用域链到闭包

    一.作用域 全局作用域和函数作用域(局部作用域). 一个变量的作用域就是源代码中定义这个变量的区域. 二.作用域链和闭包 全局变量只有一个(window,globel),全局环境下每一个函数都会形成一 ...

  9. 【MarkMark学习笔记学习笔记】javascript/js 学习笔记

    1.0, 概述.JavaScript是ECMAScript的实现之一 2.0,在HTML中使用JavaScript. 2.1 3.0,基本概念 3.1,ECMAScript中的一切(变量,函数名,操作 ...

随机推荐

  1. 真正从底层理解 Synchronized 实现原理

    实现synchronized的基础有两个:Java 对象头和 Monitor. 在虚拟机规范中定义了对象在内存中的布局,主要由以下 3 部分组成: 对象头 实例数据 对齐填充 而synchronize ...

  2. andriod开发中遇到的错误

    1.java.net.UnknownServiceException: CLEARTEXT communication ** not permitted by network security pol ...

  3. kvm-virtualization – 删除“孤儿”libvirt快照

    原文链接:https://codeday.me/bug/20181110/371346.html 创建快照: virsh snapshot-create-as --domain prod snap - ...

  4. 0基础掌握接口测试神器-Postman

    一:Postman环境搭建 1:postman是什么?Postman是一款功能强大的网页调试与发送网页HTTP请求的接口测试工具.2:postman有几种安装方式?两种,应用程序和浏览器插件 3:po ...

  5. 数据中台实战(一):以B2B电商亿订为例,谈谈产品经理视角下的数据埋点

    本文以B2B电商产品“亿订”为实例,与大家一同谈谈数据中台的数据埋点. 笔者所在公司为富力环球商品贸易港,是富力集团旗下汇聚原创设计师品牌及时尚买手/采购商两大社群,通过亿订B2B电商.RFSHOWR ...

  6. jmeter参数化之 【CSV Data Set Config/CSV数据配置文件】

    这里以登录功能为例: 1.新建.txt文件,将参数值写入到txt文件中(多个参数值如:用户名,密码 之间以逗号隔开),将文件放置在想要放置的目录下 2.添加csv数据文件设置 右键线程组->添加 ...

  7. [CSP-S2019]划分 题解

    CSP-S2 2019 D2T2 考场上读完题感觉是DP就直接扔了开T3了,考完才发现部分分好像不难拿,枯了 题意分析 给出一个数列,要求将其分成几段,使每段的和非严格递增,求最小的每段的和的平方和. ...

  8. JDBC | 第七章: JDBC数据库连接池使用

    概述 数据库连接池是负责分配.管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个.那么其中的运行机制又是怎样的呢?今天主要介绍一下数据库连接池原理和常用的连接池. ...

  9. 使用IDEA创建一个SSM工程(非maven)

    说在前面的话 直到现在从Eclipse向IDEA转的人越来越多,但是IDEA的项目创建让人摸不清头脑,因此这里我创建一个非maven的ssm工程,供大家练练手,进一步的了解IDEA在项目中的使用. 创 ...

  10. Android Studio出现:Your project path contains non-ASCII 错误代码解决方法

    导入Project的出现: Error:(1, 0) Your project path contains non-ASCII characters. This will most likely ca ...