JS基础学习——闭包

什么是闭包

闭包的定义如下,它的意思是闭包使得函数可以记住和访问它的词法范围,即使函数是在它声明的词法范围外执行。更简单来讲,函数为了自己能够正确执行,它对自己的词法范围产生闭包,在它执行完毕释放之前,它会阻止相关的词法范围提早关闭释放。

Closure is when a function is able to remember and access its lexical scope even when that function is executing outside its lexical scope.

一个比较简单的例子就是嵌套查询,如code 1所示,因为bar函数需要访问foo函数内的变量a,因此bar对foo的内部范围产生了闭包,但在这个例子中bar函数是在其声明时的词法范围内执行的,因此闭包现象不能很好体现,但是需要知道在这种嵌套函数中闭包也是存在的。

/*-----------code 1----------*/
function foo() {
var a = 2;
function bar() {
console.log( a ); // 2
}
bar();
}
foo();

code 2中闭包现象比较明显,按照函数作用域的理解,函数内部的变量在函数运行结束之后就应该消亡,但由于bar对foo的内部范围产生了闭包,使得bar在foo执行完毕之后还能继续访问foo的内部变量,具体来说,由于bar有对foo内部变量存在引用,因此在bar作为返回值被传递出去时对foo产生了闭包,这使得foo内部的变量继续存在,bar在词法范围外部执行时也能根据自己定义时的词法范围成功找到了a变量。需要注意,由于闭包占用内存空间,所以要谨慎使用闭包。尽量在使用完闭包后,及时解除引用,以便更早释放内存,如code 2中最后一句所示。

/*-----------code 2----------*/
function foo() {
var a = 2;
function bar() {
console.log( a );
}
return bar;
}
var baz = foo();
baz(); // 2 -- Whoa, closure was just observed, man.
baz = null;

循环闭包中的经典例子

code 3设计之初是希望arr中存放的2个方法的运行结果分别是0和1,但是由于两个function都对同一个变量i具有闭包,而变量i在循环的过程中发生了改变,因此最终运行结果不是希望的那样,两个方法都将返回2。

想要实现原先的设计目标,有两种方法可以实现,第一种是使用IIFE创建函数作用域,如code 4所示,第二种方法是使用let关键词,如code 5所示,let声明的循环变量绑定的是单次迭代作用域,每次迭代都会产生一个新的同名循环变量,具体看JS基础学习——作用域

/*-----------code 3----------*/
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var bar = foo();
console.log(bar[0]());//2 /*-----------code 4----------*/
function foo(){
var arr = [];
for(var i = 0; i < 2; i++){
arr[i] = (function fn(j){
return function test(){
return j;
}
})(i);
}
return arr;
}
var bar = foo();
console.log(bar[0]());//0 /*-----------code 5----------*/
function foo(){
var arr = [];
for(let i = 0; i < 2; i++){
arr[i] = function(){
return i;
}
}
return arr;
}
var bar = foo();
console.log(bar[0]());//0

模块中的闭包

一个函数,它以对象为返回值,且对象中至少包含一个属性为内部函数,且该内部函数访问函数的私有变量(蕴含闭包),那么这个函数就是一个模块,有点类似于c++、java中的类概念。code 6就是一个模块函数。

/*-----------code 6----------*/
var foo = (function CoolModule() {
var something = "cool";
var another = [1, 2, 3];
function doSomething() {
console.log( something );
}
function doAnother() {
console.log( another.join( " ! " ) );
}
return {
doSomething: doSomething,
doAnother: doAnother
};
})();
foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3

参考资料:

[1] You don't know js -- Scope & Closures

[2] 深入理解闭包系列第四篇——常见的一个循环和闭包的错误详解

JS基础学习——闭包的更多相关文章

  1. JS基础学习——对象

    JS基础学习--对象 什么是对象 对象object是JS的一种基本数据类型,除此之外还包括的基本数据类型有string.number.boolean.null.undefined.与其他数据类型不同的 ...

  2. JS基础学习——作用域

    JS基础学习--作用域 什么是作用域 变量的作用域就是变量能被访问到的代码范围,比如在下面的这个js代码中,变量a的作用域就是函数foo,因此在全局作用域内的console.log(a)语句不能访问到 ...

  3. JS 基础学习随想

    2012年就已经接触过了js,给我的印象:这是一门谈不上复杂的语言.大概这就是所谓的学的越浅,用的越少,觉得自己会的东西好像得更多吧!开始做基础练习题的时候觉得好像都十分简单.可是后来在做到对象数组的 ...

  4. handlebars.js基础学习笔记

    最近在帮学校做个课程网站,就有人推荐用jquery+ajax+handlebars做网站前端,刚接触发现挺高大上的,于是就把一些基础学习笔记记录下来啦. 1.引用文件: jquery.js文件下载:h ...

  5. JS基础学习1

    1 JS 概述 一个完整的javascript实现是由以下3个不同部分组成的: (1)     核心(ECMAscript) (2)     文档对象模型(DOM)  Document object ...

  6. 两万字Vue.js基础学习笔记

    Vue.js学习笔记 目录 Vue.js学习笔记 ES6语法 1.不一样的变量声明:const和let 2.模板字符串 3.箭头函数(Arrow Functions) 4. 函数的参数默认值 5.Sp ...

  7. JS基础学习篇(一)

    近来一直在学习js和jquery.刚刚进入前端工作还没有多久,虽然大学里学习的是编程自认为也学的还可以,但前端接触的不多,一直认为前端十分简单.其实不然,特别是工作的时候要自己设计一个完整的项目前端, ...

  8. Node.js基础学习四之注册功能

    前言:在Node.js学习(二)和(三)中介绍了如何在Node.js 中获取登录的用户名和密码与数据库进行验证并返回数据给客户端 需求:实现注册功能 为了区分登录和注册是两个不同的请求,在端口后面加上 ...

  9. JS基础学习(二)

    昨天把网站上的基础知识看完了,下面是剩下的部分 第六节 JS Window浏览器对象模型 JavaScript全局对象,函数,变量均自动成为window对象的成员. 1.Window对象 1.获取浏览 ...

随机推荐

  1. 公共子序列(luogu P1439)

    传送门 题目描述 给出1-n的两个排列P1和P2,求它们的最长公共子序列. 输入输出格式 输入格式: 第一行是一个数n, 接下来两行,每行为n个数,为自然数1-n的一个排列. 输出格式: 一个数,即最 ...

  2. DIV做的Table

    <style> div.table{ border:1px solid #d7d7d7; margin-left:0px; border-bottom-width:; width:1200 ...

  3. Reviewing notes 2.1 of Mathematical analysis

    Chapter2 Numerical sequence and function Cartesian product set If S and T are sets,then the cartesia ...

  4. [jvm]java内存模型

    一.java内存模型 Java虚拟机规范中试图定义一种Java内存模型(Java Memory Model,JMM)来屏蔽掉各种硬件和操作系统的内存访问差异,以实现让Java程序在各种平台下都能达到一 ...

  5. linux下蓝牙开发(bluez应用)

    编译blueZ-5.25 需要先编译安装以下包: bluez-libs-3.36.tar.gz expat-2.1.0.tar.gz dbus-1.10.0.tar.gz glib-2.26.1.ta ...

  6. Linux系统管理之硬盘管理

    硬盘是计算的重要组成部件之一,硬盘为操作系统提供持久话存储的功能,在Linux硬盘设备的性能和好坏可能关系到生成线的安全和用户体验等等.熟练的掌握硬盘管理相关的信息能让我们处理起这些问题来得心应手. ...

  7. [BJOI2012]连连看 BZOJ2661 费用流

    题目描述 凡是考智商的题里面总会有这么一种消除游戏.不过现在面对的这关连连看可不是QQ游戏里那种考眼力的游戏.我们的规则是,给出一个闭区间[a,b]中的全部整数,如果其中某两个数x,y(设x>y ...

  8. 4A - Horse

    打表找规律 #include <iostream> #include <queue> using namespace std; ][]; ]{, , , , -, -, -, ...

  9. 创建React工程

    下载 main.jsBundle 包curl http://localhost:8081/index.ios.bundle -o main.jsbundle <!DOCTYPE html> ...

  10. eclipse 远程文件实时同步,eclipse远程部署插件

    [转自] http://zhwj184.iteye.com/blog/1842730 eclipse 远程文件实时同步,eclipse远程部署插件 github地址:https://github.co ...