简介

  一个定义在函数内部的函数与包含它的外部函数构成了闭包,内部函数可以访问外部函数的变量,这些变量将一直保存在内存中,直到无法再引用这个内部函数。

例如:

var a = 0;
function outerFun(i) {
var b = i;
function innerFun(j) {
var c = j;
console.log("全局变量:"+a);
console.log("外部变量:"+b);
console.log("内部变量:"+c);
a++;
b++;
c++;
}
return innerFun;
}
var testFun1 = outerFun(10);
testFun1(10);//全局变量:0 外部变量:10 内部变量:10
testFun1(10);//全局变量:1 外部变量:11 内部变量:10 var testFun2 = outerFun(20);
testFun2(20);//全局变量:2 外部变量:20 内部变量:20
testFun2(20);//全局变量:3 外部变量:21 内部变量:20

结论:

c 是 innerFun() 的局部变量,每次执行 innerFun() 都会重新赋值;
b 是 innerFun() 的上一级变量,每次执行 innerFun() 的结果会保存在内存中,是 outerFun() 的局部变量,每次执行 outerFun() 都会重新赋值;
a 是 innerFun() 的上上一级变量,每次执行 innerFun() 的结果会保存在内存中,是 outerFun() 的上一级变量,每次执行 outerFun() 的结果也会保存在内存中;

  在JavaScript中,作用域只有全局作用域和函数级作用域两种,在下一级作用域中可以访问和修改上一级作用域的变量,在定义函数时,JS会自动维护一个作用域链,当前的局部作用域位于作用域链顶端,并可以依次向上回溯。闭包的实质就是延长了作用域链。

变量的生存周期

  上面提到,js 中只有全局变量和函数级的局部变量两种,全局变量的生存周期当然是永久的,除非我们主动销毁这个全局变量。而对于在函数内用 var 关键字声明的局部变量来说,当退出函数时,这些局部变量即失去了它们的价值,它们都会随着函数调用的结束而被销毁。

例如:

//页面有5个 div,期望点击每个 div 输出它的序号
for(var i=0; i<5; i++) {
$('div').eq(i).on('click',function() {
console.log(i);
})
}

然而,实际上,点击每个 div 输出的都是5,这是因为 i 是全局变量,位于作用域链最顶端,当改变 i 的值的时候,所有引用了它的函数都会受到影响,当循环运行结束后,i 的最终值为5,所以点击每个 div 输出的当然是5了。这时我们可以通过闭包来延长作用域链,为 i 的值保存一个副本,使它们之间不会互相影响。

例如:

for(var i=0; i<5; i++) {
function outerFun() {
var j = i;
function innerFun() {
$('div').eq(j).on('click',function() {
console.log(j);
})
}
innerFun();
}
outerFun();
}

这里的 outerFun() 和 innerFun() 都可以用匿名自执行函数代替,例如:

for(var i=0; i<5; i++) {
(function() {
var j = i;
(function() {
$('div').eq(j).on('click',function() {
console.log(j);
})
})();
})();
}

JS基础:闭包和作用域链的更多相关文章

  1. [ JS 进阶 ] 闭包,作用域链,垃圾回收,内存泄露

    原网址:https://segmentfault.com/a/1190000002778015 1. 什么是闭包? 来看一些关于闭包的定义: 闭包是指有权访问另一个函数作用域中变量的函数 --< ...

  2. JS闭包、作用域链、垃圾回收、内存泄露相关知识小结

    补充: 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 闭包的三个特性: 1.函数嵌套函数 2.函数内部可以引用外部的参数和变量 3.参数和变 ...

  3. Javascript中闭包的作用域链

    作用域定义了在当前上下文中能够被访问到的成员,在Javascript中分为全局作用域和函数作用域,通过函数嵌套可以实现嵌套作用域. 闭包一般发生在嵌套作用域中.闭包是JavaScript最强大的特性之 ...

  4. JS基础篇之作用域、执行上下文、this、闭包

    前言:JS 的作用域.执行上下文.this.闭包是老生常谈的话题,也是新手比较懵懂的知识点.当然即便你作为老手,也未必真的能理解透彻这些概念. 一.作用域和执行上下文 作用域: js中的作用域是词法作 ...

  5. js学习笔记之作用域链和闭包

    在学习闭包之前我们很有必要先了解什么是作用域链 一.作用域链 作用域链是保证对执行环境有权访问的所有变量和函数的有序访问. 这句话其实还是蛮抽象的,但是通过下面一个例子,我们就能清楚的了解到作用域链了 ...

  6. 对js中闭包,作用域,原型的理解

    前几天,和朋友聊天,聊到一些js的基础的时候,有一种‘好像知道,好像又不不知道怎么讲的感觉’...于是捡起书,自己理一理,欢迎拍砖. 闭包 理解闭包首先要理解,js垃圾回收机制,也就是当一个函数被执行 ...

  7. javascript闭包和作用域链

    最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...

  8. Javascript——闭包、作用域链

    1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...

  9. JS -- The Scope Chain 作用域链

    The Scope Chain JavaScript is a lexically scoped language: the scope of a variable can be thought of ...

随机推荐

  1. Unity UGUI基础之Text

    Text作为UGUI最基础的控件以及最常用的控件,它在项目中的应用绝对可以算是最多的,任何一个UI界面可以说都离不开它,它的基本属性如下: 一.rect transform组件: rect trans ...

  2. Java:函数,类,数组之间的运用

    在我的demoe类中,我实现了以下方法: 这个类在另外一个文件,demoe.java中 public class Demoe { //计算一个数字因子的个数 public static int get ...

  3. Chapter 1 Securing Your Server and Network(13):配置端点安全性

    原文出处:http://blog.csdn.net/dba_huangzj/article/details/38489765,专题目录:http://blog.csdn.net/dba_huangzj ...

  4. MinerThreadPool.java 线程池

    MinerThreadPool.java 线程池 package com.iteye.injavawetrust.miner; import java.util.concurrent.Blocking ...

  5. C++ Primer 有感(顺序容器)

    1.顺序容器的元素排列次序与元素的值无关,而是由元素添加到容器里的次序决定. 2. 顺序容器 vector                               支持快速随机访问 list   ...

  6. leetcode 104 Maximum Depth of Binary Tree二叉树求深度

    Maximum Depth of Binary Tree Total Accepted: 63668 Total Submissions: 141121 My Submissions Question ...

  7. 【linux】mkfifo 命令创建命名管道实现进程之间通信

    mkfifo 命令 mkfifo命令创建一个FIFO特殊文件,是一个命名管道(可以用来做进程之间通信的桥梁) 管道也是一种文件,一般是linux中的一个页大小,4k,管道数据一旦被读取就没了.(管道大 ...

  8. HBase写数据

    1 多HTable并发写 创建多个HTable客户端用于写操作,提高写数据的吞吐量,一个例子: static final Configuration conf = HBaseConfiguration ...

  9. 报表打印错误:Forcing NLS_NUMERIC_CHARACTERS to: '.,' for XDO processing

    HDSP0004 module: HDSP: 凭证打印 +----------------------------------------------------------------------- ...

  10. 【Java编程】Java基本数据类型

    在较前面的一篇博文<C/C++基本数据类型>中,我主要介绍了c/c++的基本数据类型.我们知道C语言没有具体规定各类数据类型所占内存的字节数,只要求long型数据长度不小于int型,sho ...