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

一、作用域链

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

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

 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. SSM框架整合练习——一个简单的文章管理系统

    使用SSM框架搭建的简易文章管理系统,实现了简单的增删改查功能. @ 目录 开发工具版本: 最终的项目结构 IDEA+Maven搭建项目骨架 1. 新建Maven项目: 2. 在新建的项目中添加所需要 ...

  2. Mybatis_day1

    mybatis框架的引入: JDBC里面 对功能实现的进一步封装,可以按照以下方式操作 Student s = new Student(id,name); util.save(s); ORM: obj ...

  3. sqlalchemy怎么order_by降序/升序并取第一条数据

    原文链接:https://blog.csdn.net/mark4541437/article/details/103755721 sqlalchemy怎么order_by降序/升序并取第一条数据 fr ...

  4. 自动化项目Jenkins持续集成

    一.Jenkins的优点 1.传统网站部署流程   一般网站部署的流程 这边是完整流程而不是简化的流程 需求分析—原型设计—开发代码—内网部署-提交测试—确认上线—备份数据—外网更新-最终测试 ,如果 ...

  5. Linux环境下安装Redis数据库

    1.下载Redis安装包 访问https://redis.io/download,目前最新版本是5.0.5,点击下载 2.安装Redis 2.1通过远程工具把压缩包导入Linux工作盘,我的在home ...

  6. Java数据结构——循环链表

    一.单向循环链表表中的最后一个节点的指针域指向头结点,整个链表形成一个环.其他的与单链表相同. (以下图片均来自网络,侵删) 插入操作 删除操作 简单实现 public class CiNode { ...

  7. 3D渲染集群,你了解多少?

    摘要:渲染是批处理运行模式,那能不能使用Docker容器技术,做大规模的渲染集群呢? 我们先说说3D渲染涉及哪些领域: 1.什么是3D渲染 简单粗暴的讲:就是将虚拟世界里的3D模型,变为(人眼看到)平 ...

  8. 看视频常见的 720p、1080p、4k,这些分辨率到底包含了什么

    从早期的420p,到后来的720p,到现在的非1080p不看.视频的清晰度飞快提升,但是在看到色彩越来越丰富清晰度越来越高的画面时,你有关注过他们的到底是怎么做到的么?我们一起来了解一下吧. 想必大家 ...

  9. wmz的数数(数状数组)

    wmz的数数(数状数组) 题目描述 \(wmz\)从小就显现出了过人的天赋,他出生的第三天就证明了哥德巴赫猜想,第五天就证明了质能方程,出生一星期之后,他觉得\(P\)是否等于\(NP\)这个问题比前 ...

  10. Asp.Net Core3.x中使用Cookie

    在Asp.Net中使用Cookie相对容易使用,Request和Response对象都提供了Cookies集合,要记住是从Response中存储,从Request中读取相应的cookie.Asp.Ne ...