有趣的闭包

一、闭包的概念

引用《JavaScript权威指南》的定义:函数体内部的变量都可以保存在函数作用域中,这个特性叫做“闭包”。如果函数定义是变量就在某个作用域上,它就跑不掉了。何时何地调用函数,它都能在自己相应的作用域链上找到自己所需要的变量。这个就是闭包在js中起到的作用。闭包其实就是js特有的函数作用域的一个概念。

var scope = 'global scope';
function checkScope(){
     var scope = 'local scope';
     function f(){
       return scope; 
     }
     return f();
}
checkScope();   // 'local scope' 这里拿到的依然是局部变量  这叫闭包

二、闭包中的局部变量不会被回收

1. 从作用域链入手

作用域链从何而来?从定义到调用

1. 当定义一个函数时,(js解析器)实际上保存了一个与之相关的作用域链。

2. 当调用这个函数时,它创建了一个新的对象来存储它的局部变量。

那当函数嵌套且返回一个函数时(闭包)我们来看是怎么回事?

如a()函数中嵌套了b()函数,而a中定义的局部变量c在b中调用,且返回b函数。但调用外部函数a()执行完,虽然它自己的作用域链没了,但是返回的b()函数有自己的作用域链,且b的作用域链上有a定义的局部变量c,当返回b()时候,b的作用域链绑定的新的对象来保存接手局部变量c,所以c不会被回收内存。

var scope = 'global scope';
function checkScope(){
     var count = 0 ;
     function f(){
       return count++; 
     }
     return f();
}
checkScope();   // = 1
checkScope();   // = 2 因为局部变量count没有在上一次外部函数checkScope调用完之后并没有销毁。

2.《JavaScript权威指南》的描述

        如果函数中定义了嵌套函数,并将这个嵌套函数作为返回值返回或者存储在某处的属性里,这时就会有一个外部引用指向这个嵌套函数,它就不会被当做垃圾回收,并且它所指向的变量绑定对象也不会被当做垃圾回收!

3.《JavaScript高级编程》

        垃圾回收机制原理:找出那些不再继续使用的变量,然后释放其占用的内存。

显然,闭包中的局部变脸在返回的函数中仍然需要,所以闭包中的局部变量不会被回收内存。

三、闭包发挥的作用

1. 用于保护命名空间,不污染全局变量。

特别是在一些你需要保存上次结果的累计的时候,你可以定义一个全局变量,当时由于真个js文档很大,你可能忘记之前你定义过这个同名全局变量或者别人定义过,所以你再次定义全局变量时,会有覆盖污染可能存在的同名全局变量的风险,所以用闭包保存局部变量当“全局变量”的方法可以规避这个风险!

2. 利用闭包原理对私有变量进行类封装

我们可以通过将变量或者参数闭包在一个构造函数内来模拟实现私有变量,并在构造函数中定义一个函数(this.func= function(){})来访问这些私有变量(非this.a = ...定义的正常定义变量),这个函数就成了这个类的方法,在外部可以通过这个方法来访问这些私有变量!

扫描二维码关注公众号,回复: 937512 查看本文章

猜你喜欢

转载自my.oschina.net/u/3697586/blog/1548074