闭包的定义

不用解释了,网上到处都是。简单的说:一个定义在函数内部的函数与包含它的外部函数构成了闭包,内部函数可以访问外部函数的变量,这些变量将一直保存在内存中,直到无法再引用这个内部函数

举个例子:

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

结论:
    val是innerFun()的局部变量,每次执行innerFun()都会重新赋值;
    vval是innerFun()的上一级变量,每次执行innerFun()的结果会保存在内存中,是outerFun()的局部变量,每次执行outerFun()都会重新赋值;
    vvval是innerFun()的上上一级变量,每次执行innerFun()的结果会保存在内存中,是outerFun()的上一级变量,每次执行outerFun()的结果会保存在内存中;
    
在JavaScript中,作用域只有全局作用域和函数级作用域两种,在下一级作用域中可以访问和修改上一级作用域的变量,在定义函数时,JS会自动维护一个作用域链,当前的局部作用域位于作用域链顶端,并可以依次向上回溯。闭包的实质就是延长了作用域链。

再举一个例子:

//若已经定义了10个<div>,现在想用循环给每个<div>根据序号绑定不同的事件
var i;
for(i=0;i<10;i++) {
    $("div:eq("+i+")").on("click",function() {
        console.log(i);
    });
}

然而,点击每个<div>输出结果均为10,这是因为i是全局变量,当改变i的值时,所有引用了它的函数都会受到影响。这时我们可以通过延长作用域链,为i的值保存一个副本,使它们之间不会互相影响:

var i;
for(i=0;i<10;i++) {
    function outer() {
        var vval = i;
        function inner() {
            console.log(vval);
        }
        $("div:eq("+vval+")").on("click",inner);
    }
    outer();
}

每循环一次就定义了一个外部函数outer()和一个内部函数inner(),因为inner()被绑定在<div>的click事件上,所以outer()中的变量没有在执行完之后就被释放,而是保存在内存中,最后需要执行一次outer(),初始化变量vval,当然你也可以使用自执行的匿名函数代替outer()。
解释一下:在JS中函数是可以重复定义的,只是执行的是最后一次定义的函数而已,例如:

function a() {
    console.log(1);
}
a();
function a() {
    console.log(2);
}
a();
//输出两个2

JS闭包,以及适用场景的更多相关文章

  1. js闭包之应用场景

    闭包的解释 当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包 在javascript中,只有函数内部的子函数才能读取局部变量,所以说,闭包可以简单理解成“定义 ...

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

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

  3. javascript深入理解js闭包

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

  4. js闭包

    先从闭包特点解释,应该更好理解. 闭包的两个特点: 1.作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态.2.一个闭包就是当一个函数返回时,一个没有释放资源的栈区. 其实上面两点可以合成一 ...

  5. 深入理解JS闭包

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

  6. 关于JS闭包,作者不详(转)

    说明:本文由两篇文章结合而成,系从他人笔记中转过来的, 具体作者不详.因为觉得不错,遂共享之.如有侵权,立删致歉. 一.变量的作用域 要理解闭包,首先必须理解Javascript特殊的变量作用域. 变 ...

  7. js闭包之初步理解( JavaScript closure)

    闭包一直是js中一个比较难于理解的东西,而平时用途又非常多,因此不得不对闭包进行必要的理解,现在来说说我对js闭包的理解. 要理解闭包,肯定是要先了解js的一个重要特性, 回想一下,那就是函数作用域, ...

  8. JS闭包的理解

    闭包的两个特点: 1.作为一个函数变量的一个引用 - 当函数返回时,其处于激活状态.2.一个闭包就是当一个函数返回时,一个没有释放资源的栈区. 其实上面两点可以合成一点,就是闭包函数返回时,该函数内部 ...

  9. JS闭包(转载加整理)

    原文地址:http://www.jb51.net/article/24101.htm 闭包(closure)是Javascript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 一.变量 ...

  10. 理解js闭包(二)

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

随机推荐

  1. 【卸载】oracle卸载

    Oracle卸载比较麻烦,不能简单卸载就完成了,有时没有卸载完整,下次安装不能很好的安装: 当然Oracle卸载也没有那么难,只是步骤比较多.Oracle10g还是Oracle11g卸载步骤都是一样的 ...

  2. Linux-配置vim开发环境

    vim是一个类似于vi的著名的功能强大.高度可定制的文本编辑器,在vi的基础上改进和增加了很多特性.vim是纯粹的自由软件. 为了满足使用者的要求,将vim界面配置为自己想要的界面类型也变得流行起来. ...

  3. UPS对电源故障的处理能力

    UPS对电源故障的处理能力 双变换在线式UPS由于其逆变器实时在线工作,因而能对所有的电源故障具有隔离和处理功能.由于目前电网情况发生了很大变化,真正的长时间断电只占所有电源故障的30%甚至更低,而非 ...

  4. JS判断值是否是正数

    1.使用isNaN()函数 isNaN()的缺点就在于 null.空格以及空串会被按照0来处理 NaN: Not a Number /** *判断是否是数字 * **/ function isReal ...

  5. JavaScript巧学巧用

    关于 微信公众号:前端呼啦圈(Love-FED) 我的博客:劳卜的博客 知乎专栏:前端呼啦圈 前言 由于工作和生活上的一些变化,最近写文章的频率有点下降了,实在不好意思,不过相信不久就会慢慢恢复过来, ...

  6. bootstrap的常用组件和栅格式布局

    Bootstrap 是最受欢迎的 HTML.CSS 和 JS 框架,用于开发响应式布局.移动设备优先的 WEB 项目. 因为Bootstrap需要jquery的支持,所以在使用Bootstrap之前要 ...

  7. C# 创建压缩文件

    在程序中对文件进行压缩解压缩是很重要的功能,不仅能减小文件的体积,还能对文件起到保护作用.如果是生成用户可以下载的文件,还可以极大的减少网络流量并提升下载速度.最近在一个 C# 项目中用到了创建压缩文 ...

  8. JavaScript、Python、java、Go算法系列之【快速排序】篇

    常见的内部排序算法有:插入排序.希尔排序.选择排序.冒泡排序.归并排序.快速排序.堆排序.基数排序等. 用一张图概括: 选择排序 选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的 ...

  9. Spring入门导读——IoC和AOP

    和MyBatis系列不同的是,在正式开始Spring入门时,我们先来了解两个关于Spring核心的概念,IoC(Inverse of Control)控制反转和AOP()面向切面编程. 1.IoC(I ...

  10. Linux 下按时间顺序批量删除文件

    ls -lrt| awk '{print $9}'| head -n 10 | xargs rm -rf 1.文件按时间排序: 2.获取文件名字: 3.取前10个文件 4.删除文件