为什么80%的码农都做不了架构师?>>>   

(一)什么是闭包?

  • 闭包就是函数的局部变量集合,只是这些局部变量在函数执行结束后会继续存在(仍然能被外部访问),即函数的“堆栈”在函数返回后并不释放(我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配)。
  • 当在一个函数内定义另外一个函数就会产生闭包。

提问:如何在函数执行完毕后,外部仍然能够访问函数内的局部变量?

回答:JavaScript的方式,函数必须返回一个“指向闭包”的“引用”,或将这个”引用”赋值给某个外部变量。举例:

function closure(name)
{
    var text = "Hello, "+name;
    //每次调用时,产生闭包,并返回内部函数对象给调用者
    return function(){
        alert(text);
    };
}
var yinyong = closure("Wish");

yinyong();//yinyong()函数在closure函数执行完毕后,仍然可以访问到了定义在其之内的局部变量text。

(二)闭包内的微观世界

function a(){
 var i=0;
 function b(){
     alert(++i);
 }
 return b;
}
var c = a();
c();

如果要更加深入的了解闭包以及函数a和嵌套函数b的关系,我们需要引入另外几个概念:函数的执行环境(excution context)、活动对象 (call object)、作用域(scope)、作用域链(scope chain)。以函数a从定义到执行的过程为例阐述这几个概念。

1、当定义函数a的时候,js解释器会将函数a的作用域链(scope chain)设置为定义a时a所在的“环境”,如果a是一个全局函数,则scope chain中只有window对象。
2、当函数a执行的时候,a会进入相应的执行环境(excution context)。
3、在创建执行环境的过程中,首先会为a添加一个scope属性,即a的作用域,其值就为第1步中的scope chain。即a.scope=a的作用域链。
4、然后执行环境会创建一个活动对象(call object)。活动对象也是一个拥有属性的对象,但它不具有原型而且不能通过JavaScript代码 直接访问。创建完活动对象后,把活动对象添加到a的作用域链的最顶端。此时a的作用域链包含了两个对象:a的活动对象和window对象。
5、下一步是在活动对象上添加一个arguments属性,它保存着调用函数a时所传递的参数。
6、最后把所有函数a的形参和内部的函数b的引用也添加到a的活动对象上。在这一步中,完成了函数b的的定义,因此如同第3步,函数b的作用域链被设置为b所被定义的环境,即a的作用域。

到此,整个函数a从定义到执行的步骤就完成了。此时a返回函数b的引用给c,又函数b的作用域链包含了对函数a的活动对象的引用,也就是说b可以访问到a中定义的所有变量和函数。函数b被c引用,函数b又依赖函数a,因此函数a在返回后不会被GC回收。

当函数b执行的时候亦会像以上步骤一样。因此,执行时b的作用域链包含了3个对象:b的活动对象、a的活动对象和window对象,如下图所示:

如图所示,当在函数b中访问一个变量的时候,搜索顺序是先搜索自身的活动对象,如果存在则返回,如果不存在将继续搜索函数a的活动对象,依 次查找,直到 找到为止。如果整个作用域链上都无法找到,则返回undefined。如果函数b存在prototype原型对象,则在查找完自身的活动对象 后先查找自 身的原型对象,再继续查找。这就是Javascript中的变量查找机制。

(三)闭包的应用

例子1:闭包中局部变量是引用而非拷贝

function say51()
{
    var num = 50;
    var infunc = function(){
        alert(num);
    };
    num++;
    return infunc;
}
var say = say51();
say();

例子2:多个函数绑定同一个闭包,因为他们定义在同一个函数内。

function sayNum()
{
    //以下三个引用对象,不是使用var声明的,所以是全局对象
    sayAlert = function(){alert(num);};
    sayAdd = function(){num++;};
    saySet = function(x){num=x;};
    var num = 50;//变量的声明,在内部函数定义之后!
}
sayNum();//初始化全局对象
sayAlert();
sayAdd();sayAlert();
saySet(1);sayAlert();

例子3:当在一个循环中赋值函数时,这些函数将绑定同样的闭包

var outer = [];//函数数组
function fun()
{
    var arr = ["a","b","c"];
    for(var i=0;i<arr.length;i++)//i的作用域在整个函数内
    {
        var x = {};
        x.value = arr[i];
        x.getID = function(){
            console.log(i);
        };
        outer.push(x);
    }
    console.log("执行fun函数 i="+i+" x.value="+x.value);
}
fun();//在循环中赋值函数
console.log(outer[0].value);
console.log(outer[1].value);
console.log(outer[2].value);
outer[0].getID();
outer[1].getID();
outer[2].getID();

利用闭包产生单件的方法:通过闭包完成私有的成员和方法的封装。
匿名主函数返回一个对象,对象包含了两个方法,方法1可以方法私有变量,方法2访 问内部私有函数。
需要注意的地方是匿名主函数结束的地方的’()’,如果没有这个’()’就不能产生单件。因为匿名函数只能返回了唯一的对象,而且不能被 其他地方调用。
var singleton = function () {
    var privateVariable;
    function privateFunction(x) {
        ...privateVariable...
    }
    return {
        firstMethod: function (a, b) {
            ...privateVariable...
        },
        secondMethod: function (c) {
            ...privateFunction()...
        }
    };
}();

转载于:https://my.oschina.net/ffwcn/blog/209467

JavaScript的闭包与应用相关推荐

  1. 深入理解javascript的闭包

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

  2. Javascript的闭包及其使用技巧实例

    Javascript的闭包及其使用技巧实例 一.闭包的基本概念 闭包(Closure)是一个引用了自由变量的函数,记录了该函数在定义时的scope chain.又称词法闭包(Lexical Closu ...

  3. JavaScript中闭包实现的私有属性的getter()和setter()方法

    注意: 以下的输出都在浏览器的控制台中 <!DOCTYPE html> <html> <head><meta charset="utf-8" ...

  4. 深入理解JavaScript的闭包特性如何给循环中的对象添加事件

    初学者经常碰到的,即获取HTML元素集合,循环给元素添加事件.在事件响应函数中(event handler)获取对应的索引.但每次获取的都是最后一次循环的索引.原因是初学者并未理解JavaScript ...

  5. JavaScript:闭包

    在说JavaScript中闭包概念之前,我们先来了解一下作用域和变量生命周期的问题.作用域在前面的博客中有提到,大家可以点击查看一下,关于变量的生命周期,什么是生命周期?也就是变量从创建到销毁的一个过 ...

  6. mysql闭包的概念_彻底搞懂JavaScript的闭包、防抖跟节流

    最近出去面试了一下,收获颇多!!! 以前的我,追求实际,比较追求实用价值,然而最近面试,传说中的面试造火箭,工作拧螺丝,竟然被我遇到了.虽然很多知识点在实际工作中并不经常用到,但人家就是靠这个来筛选人 ...

  7. 关于JavaScript的闭包(closure)

    (转载自阮一峰博客) 闭包(closure)是Javascript语言的一个难点,也是它的特色,更是函数式编程的重要思想之一,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于Javascri ...

  8. JavaScript学习--闭包

    1.作用域链 JavaScript与很多程序设计语言不同,它不存在大括号级的作用域,但它有函数作用域,也就是说,在函数内定义的变量在函数外是不可见的 2.闭包在Getter和Setter的应用 var ...

  9. javascript中闭包的一些理解

    闭包是javascript中绕不开的话题,关于闭包的一些概念和应用,这方面资料比较多,在此就不再赘述.众所周知,闭包的一个作用就是 让一些变量始终保持在内存中 ,在此我用一些实际代码对这句话作进一步的 ...

  10. Javascript中闭包的作用域链

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

最新文章

  1. hello python jpush api_jpush python服务器端
  2. CodeForces - 261B Maxim and Restaurant
  3. 安卓StepView事件进度条的简单实现
  4. Ubuntu 编译安装python3.7
  5. jQuery EasyUI布局容器layout实例精讲
  6. 【git】强制覆盖本地代码(与git远程仓库保持一致)
  7. jasmine.FunctionMatchers.toHaveBeenCalledWith的单步调试
  8. 如何维护笔记本电脑的电池
  9. 第十一届蓝桥杯A组省赛填空试题 A: 门牌制作(Java)
  10. Linux C 深入分析结构体指针的定义与引用
  11. C# 多个线程一直跑着While(true)
  12. mysql安全措施_MySQL数据库在网络安全方面的一些防御措施
  13. Nginx安装的两种方法
  14. java 序列化 学习
  15. 各种泵的图形符号_水泵cad画法
  16. 网页导出pdf不完整_网页怎么打印成PDF文件?使用这款工具轻松实现
  17. 纵行科技联合Kinéis等欧洲企业,开发ZETA星地融合低功耗物联网芯片
  18. 从user 登陆开始
  19. torch.Tensor(dim)与torch.Tensor((dim)), torch.Tensor(dim1,dim2)与torch.Tensor((dim1,dim2))的区别
  20. 基于 Vue JS、Element UI、Nuxt JS的项目PC端前端手册

热门文章

  1. 【问题解决】线程间操作无效:从不是创建控件“textBox1”的线程访问它
  2. 远程源已存在于“ git push”到新存储库中
  3. 如何连接(合并)数据框(内部,外部,左侧,右侧)
  4. win11组策略如何开启自动更新 Windows11组策略开启自动更新的设置方法
  5. win11休眠选项在哪 Windows11没有休眠选项的解决方法
  6. get,post网络请求
  7. mysql 与c_mysql基础:mysql与C结合实例
  8. Car-like robot运动参数校准(图片版)
  9. 什么舱位_海运出口中FOB条款是什么意思?
  10. python中copy和deepcopy的区别_python里shadowcopy和deepcopy的区别