学了JavaScript有一段时间了,但是对闭包还是不太理解,于是怀着心中的疑问做了几个小实验,终于有点明白了。

首先看一下MDN上的定义:闭包是函数和声明该函数的词法环境的组合。

简单来说,闭包是一种现象。

我在搞清楚了2个概念后,理解了闭包。

首先是关于函数以及函数调用的概念:

我们来做一个简单的实验:

 function foo () {
var a = 1;
function bar () {
console.log(a)
}
return bar;
} var first = foo();
console.log(first); // 显示结果:
// ƒ bar () {
// console.log(a)
// }

作为一个初学者,有一些小细节很容易干扰我的判断。

首先要理解的是function f () {}是在声明一个函数,要执行这个函数必须用f()进行调用。

f()调用函数后,js引擎会执行函数中的代码,如果函数最后有写return ...函数执行完毕才有返回值。

 var first = foo();

表示把函数foo执行完毕后的返回值赋值给first,函数foo执行的操作是声明了一个变量a,以及一个函数bar,然后把函数bar作为返回值返回。注意:不是把bar的执行结果返回,而是把这个函数本身返回。所以first就指向了函数bar。

其次是关于执行环境与作用域的概念

作用域的定义:作用域是一套规则,用于确定在何处以及如何查找标识符。

我对作用域的理解是:代码起作用的范围。

执行环境的定义:执行环境定义了变量或函数有权访问的其他数据。每个执行环境都有三个重要的属性,变量对象(Variable object,VO)、作用域链(Scope chain)和 this。环境中定义的所有变量和函数都保存在变量对象中

我对执行环境的理解:存储一块代码中定义的所有的变量和函数的值。

因为全局作用域范围最广,所以函数内部也可以访问到全局变量。

函数内部代码执行的时候,发现某个变量的值在自己的执行环境中没有,就需要去上级执行环境中找。函数执行完毕后,当前函数的执行环境就被销毁,所以上级函数没有办法访问内部函数中声明的变量。

第二个小实验:

 function foo () {
var a = 1;
function bar () {
console.log(a)
}
return bar;
} var first = foo();
console.dir(first);

显示结果如图所示:

first就是函数bar,它能访问自己的作用域,上级foo的作用域,以及全局作用域。

当js执行first的时候,first能访问自己的作用域,上级foo的作用域,以及全局作用域。这种现象就是闭包。

闭包最大用处有两个:一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。所以我们就可以利用闭包来创建模块机制:

 function count() {
var number = 0;
return{
add : function(x){
if(x==undefined) {
number += 1;
}else{
number +=x;
}
},
reduce: function(x) {
if(x==undefined) {
number -= 1;
}else{
number -=x;
}
},
times: function() {
return number;
}
}
}

我们可以创建复数个加法器,而互不影响。

我关于闭包的理解就到这里了,如果你还不明白,就自己动手写代码试验吧!

理解JS闭包的几个小实验的更多相关文章

  1. javascript深入理解js闭包(转)

    javascript深入理解js闭包 转载  2010-07-03   作者:    我要评论 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. ...

  2. 理解JS闭包

    从事web开发工作,尤其主要是做服务器端开发的,难免会对客户端语言JavaScript一些概念有些似懂非懂的,甚至仅停留在实现功能的层面上,接下来的文章,是记录我对JavaScript的一些概念的理解 ...

  3. js的一些常用判断小实验

    下面是小实验案例 // 0 if(undefined) { console.log('1'); } else { console.log('0'); } // 0 if(null) { console ...

  4. 深入贯彻闭包思想,全面理解JS闭包形成过程

    谈起闭包,它可是JavaScript两个核心技术之一(异步和闭包),在面试以及实际应用当中,我们都离不开它们,甚至可以说它们是衡量js工程师实力的一个重要指标.下面我们就罗列闭包的几个常见问题,从回答 ...

  5. javascript深入理解js闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  6. 深入理解JS闭包

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

  7. 通俗易懂的深入理解js闭包

    闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域 ...

  8. 理解js闭包(二)

    @(编程) 一.什么是闭包? 官方"的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分. 相信很少有人能直接看懂这句话,因为他 ...

  9. javascript深入理解js闭包[转]

    一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量 ...

随机推荐

  1. Java基础--环境配置、简介

    一.环境配置 1.傻瓜式安装JDK,若提示安装JRE,将其置于JDK同一安装目录即可. 2.配置JAVA_HOME, 指向JDK的安装目录.比如 JAVA_HOME  = %JDK安装目录% 3.配置 ...

  2. 长春理工大学第十四届程序设计竞赛(重现赛)F.Successione di Fixoracci

    链接:https://ac.nowcoder.com/acm/contest/912/F 题意: 动态规划(Dynamic programming,简称dp)是一种通过把原问题分解为相对简单的子问题的 ...

  3. 这个匿名对象没有实现IComparable接口

    https://www.cnblogs.com/felixnet/p/5193086.html https://docs.microsoft.com/zh-cn/dotnet/api/system.i ...

  4. ruby YAML.load 和YAML.load_file区别

    1. load( io ) Load a document from the current io stream. File.open( 'animals.yaml' ) { |yf| YAML::l ...

  5. Java获取服务器系统默认编码格式

    大佬教的,做个笔记方法一(推荐):新建一个jsp页面在webapp下然后添加 <% out.print(System.getProperties().getProperty("file ...

  6. 【踩坑】spring每次请求后session不一样导致无法在服务器保存信息

    根据网上的资料,若想在服务器用session保存一些信息,方法如下: public Xclass Xmethod(HttpServletRequest request, HttpSession ses ...

  7. canvas雪花特效-jQuery插件实现

    这是一款效果十分逼真的html5 canvas下雪场景动画特效插件.这款下雪特效是基于Jason Brown的Snowfall jquery plugin的基础上制作的.在Snowfall jquer ...

  8. elasticsearch查询方式

    1.query string a).GET /index/type/_search ===>>查询所有 b).GET /index/type/_search?q=filed:value&a ...

  9. Yii2.0 两次奇葩的数据库连接经历

    经历一: 公司的项目经过阿里云的ECS升级后,发现在Yii2.0框架中,凡是数据库新增的字段(当然相关的表模型肯定是加了相应字段的),老是报“属性找不到”的问题,最后排查是数据库连接的问题.把127. ...

  10. jquery获取当前被选择的复选框的value的集合

    1.HTML代码 <input type="checkbox" name="productID" value="0"> < ...