个人觉得理解闭包,首先要理解以下几个概念。

1、函数的作用域和作用域链

js不像java等其他类语言,它并不存在块级作用域,取而代之的是函数作用域,另一个变量作用域是全局作用域。

函数的作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的。(摘自犀牛书P57)

在这里应该注意两点:一是函数作用域中声明提前的特性,见代码:

var scope="global"
function f(){console.log(scope);//输出结果"undefined"</span>var scope="local";console.log(scope);//输出结果"local"</span>
}

其实以上代码就相当于:

function f(){var scope; //变量声明提前console.log(scope);//输出结果"undefined"scope="local";//赋值留在原地console.log(scope);//输出结果"local"
}

这就是函数的声明提前。

需要注意的第二点就是:在函数作用域内不用var声明变量,而是直接赋值给一个变量,那么该变量就会成为全局变量。但还不仅仅是这样,千万不要把该全局变量完全等同于在全局环境中用var声明的全局变量,两者还是有一定区别的。话不多说,上代码:

var turevar=1//生命同一个不可删除的全局变量
function fun(){fakevar=2//在函数作用域内声明一个全局变量
}
this.fakevar1=3//同上
delete truevar//=>false 变量并没有被删除
delete fakevar//=>true 变量被删除
delete fakevar1//=>true 变量被删除

简单来说:var声明的全局变量,实际上定义了一个全局变量的属性,而该属性是不可配置的,也就是这个变量无法通过delete运算符删除。而未声明直接赋值的全局变量是可配置的属性,会被delete运算符删除。但是在严格模式下,第二种会报ReferenceError的错。

2、js中的执行环境和ECMAscript的执行流机制

执行环境:

定义了变量和函数有权访问的其他数据,决定了他们各自的行为。PS:每个执行环境都有一个与之相连的变量对象,如果这个环境是函数,则将其活动对象作为变量对象。

ECMAscript的执行流机制:

每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中。而在函数执行之后,栈将其环境弹出(该函数的执行环境销毁,保存在器重的所有变量核函数定义也随之销毁)——摘自:《JavaScript高级程序设计》P73

为了理解这两个概念看如下的代码:

<span style="font-size:18px;">var color="blue";
function changeColor(){var anotherColor="red";function swapColor(){var tempColor=anotherColor;anotherColor=color;color=tempColor;}
}</span>

以上代码涉及三个执行环境:全局环境、changeColor()的局部环境和swapColors()的局部环境,如图所示:

该函数的作用域链图如上图所示,其中的矩形(卧槽好难看!)表示特定的执行环境。内部环境可以通过作用链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。这些环境直接的联系是线性,有次序的,每个环境都可以向上搜索作用域链,以查询变量和函数名;但任何环境都不能通过向下搜索作用域链而进入另一个执行环境。

最后要补充的一点是:JavaScript采用词法作用域,也就是说,函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数调用时决定的。

在充分理解了以上几个概念之后,那么对于js中闭包的理解也就没那么困难了。

首先,闭包的概念:

函数对象可以通过作用域链相互关联起来,函数体内的变量可以保存在函数作用域内,这种特性被称为闭包。

为了更直观的了解闭包,先上一段代码:

var scope='global scope';//全局变量
function checkscope(){var scope="local scope";//局部变量function f(){return scope;}//在作用域中返回这个值return f();
}
checkscope()//=>输出结果local scope

理解以上代码并不难,现在对这段代码做一点的改动

var scope='global scope';
function checkscope(){var scope="local scope";function f(){return scope;}return f;
}
checkscope()();

我们知道调用函数checkscope(),我们得到的不再是一个scope值,而是一个函数f;再接着调用函数f(),这里就出现了一个问题,调用函数f是在全局环境中调用,其中的scope值从何而来?上面提到过一个概念:js是采用的词法作用域,该scope值还是来自于该函数即f定义时的作用域,而不是调用时的作用域。所以结果还是local scope。

此外,在犀牛书上还遇见一个例子比较经典。见代码:

function constfuncs(){var funcs=[];for(var i=0;i<10;i++){funcs[i]=function{ return i ;}}return funcs;
}
var funcs=constfuncs();
funcs[5]()

此时,结果的返回值是10;

结合上面的概念一步一步分析:

首先,constfuncs()函数执行以后得到的是funcs数组,数组中是十个未执行的函数function(){return i}。当调用funcs[5]()的时候,变量i的值应该是函数在定义的时候i的取值,又因为直到i=10的时候循环才停止,所以,最后i的取值是10.函数调用返回值也是10。

从这里不能看出:关联到闭包的作用域链是“活动的”。嵌套函数不会将作用域内的私有成员复制一份,也不会对所绑定的变量生成静态快照。

谈一谈对JS闭包的理解相关推荐

  1. JS闭包的理解及常见应用场景

    JS闭包的理解及常见应用场景 一.总结 一句话总结: 闭包是指有权访问另一个函数作用域中的变量的函数 1.如何从外部读取函数内部的变量,为什么? 闭包:f2可以读取f1中的变量,只要把f2作为返回值, ...

  2. 面试官:谈谈对JS闭包的理解及常见应用场景(闭包的作用)

    文章目录 对JS闭包的理解及常见应用场景(闭包的作用) 1.变量作用域 2.如何从外部读取函数内部的变量? 3.闭包概念 4.闭包用途 5.闭包的理解 6.闭包应用场景 setTimeout传参 回调 ...

  3. 浅谈对js闭包的理解

    闭包就是能够读取其他函数内部变量的函数.由于在javascript中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解成"定义在一个函数内部的函数".在本质上,闭包是将函数内 ...

  4. js闭包的理解和作用

    一.为什么引入闭包 JS为每个变量对象定了作用域,在ES5 中只有全局作用域和函数作用域,没有块级作用域,由内向外形成作用域链,函数外部不能访问函数内部作用域的局部变量.在实际开发中会带来很多不便. ...

  5. js闭包是什么?对js闭包的理解

    结合 MDN 官网中 JavaScript 章节中对闭包详解,我们需要理清的问题有,什么是闭包.闭包产生的条件.以及闭包的用途. 1.1 闭包的概念 闭包(closure)是一个函数以及其捆绑的周边环 ...

  6. js闭包的理解以及闭包中this的理解

    javascript 闭包.this 2016-01-25  js pl 闭包其实很好理解,但是由于经常把this和闭包绑在一起,从而加大了理解的难度,如果将他们分开考虑,那就清晰多了. 闭包 闭包并 ...

  7. js闭包的理解及应用场景

    函数的声明与执行 函数定义阶段 1.会在堆内存中开辟一个存储空间 把函数体放在这个空间里 函数中的所有变量不解析 2.把这个空间地址赋值给函数名 然后储存在栈内存中 函数调用阶段 1.根据函数名找到对 ...

  8. JS / 闭包的理解

    闭包实际上就是一个函数,只不过这个函数有些特殊,它定义在另一个函数内部,通过它可以在 js 中模仿出访问 C++ 中的私有成员变量的效果. 代码如下: function Test() {var cou ...

  9. js闭包深入理解(Closure)

    闭包的概念 闭包是指有权访问另一个函数作用域中的变量的函数 闭包是基于词法作用域书写代码时所产生的必然结果. 函数对象可以通过作用域关联起来,函数体内的变量都可以保存在函数作用域内,这在计算机科学文献 ...

最新文章

  1. 程序员加入新团队必问的 20 道问题
  2. python3基础教程廖雪峰云-学习廖雪峰Python3教程的pytho
  3. android之服务
  4. html语言把字变大,css怎么让字体变大?
  5. 常用 IO 模型图解介绍
  6. Glide 这样用,更省内存!!!
  7. MariaDB基础(二)
  8. 绩效管理这样做,成本减半,员工叫好!
  9. perl删除文件_Perl小知识语法重点和数据类型
  10. for循环批量写文件 shell_Shell脚本编程03下——Shell编程之循环语句
  11. Lingo建模基础入门
  12. echarts地图示例
  13. 【应用统计学】总体均值的假设检验
  14. RAID磁盘列阵介绍
  15. oracle 定义小数,Oracle中NUMBER类型如果不指定长度和小数点精度默认是多长
  16. 微信小程序退出按钮退出方式
  17. 九峰影业创始人_九峰百度百科
  18. python解椭圆方程的例题_椭圆标准方程典型例题及练习题
  19. 基于spring boot的奖助学金评审系统毕业设计源码031035
  20. win7系统ftp服务器共享文件夹权限,win7 ftp服务器 文件夹权限

热门文章

  1. 销毁铸造均衡Token的分析 - Helium
  2. Roll A Ball
  3. 一款非常好用的Markdown文档编辑器Typora
  4. 用js做一个数字华容道
  5. 大数据时代的回收生意经
  6. 纯纯写作开发者知识星球推荐
  7. 在2020年开发像TikTok这样的移动应用需要花多少钱?
  8. PVE 天龙八部TLBB服务端搭建(一)--linux环境搭建
  9. java转正自我陈述_试用期转正个人工作述职报告合集
  10. 关于数学计算机手抄报简单的,关于数学的手抄报简单