闭包(*)

前言

今天好好的研究了一下闭包,顺便写一下自己的个人理解。

什么是闭包?

闭包是指有权访问另一个函数作用域中的变量的函数。闭包有如下特点:

  • 函数嵌套函数;
  • 函数外部可以读取内部的参数和变量;
  • 参数和变量不会被垃圾回收机制回收;

常见的闭包创建方式:在一个函数内部创建另一个函数,详见下面的例子:

function Foo(){
	var typeName = 'coffee';
	return function(){
		console.log(typeName);
	}
}
var func = Foo();
func();   // "coffee"

上面的例子中,按道理,typeName是函数Foo的内部变量,在函数执行完毕后,就会被js的垃圾回收机制,回收释放,但为什么我们还可以访问到typeName呢?那就是因为我们使用了闭包,所以闭包的用途之一:可以读取到函数内部的变量。

闭包究竟是如何做到这一点的呢?

        我们能访问到某个变量,那是因为该变量包含在我们可访问的作用域链上。在上面的例子中,我们先定义了Foo()函数,然后又在全局的作用域中调用了它。当我们第一次调用Foo()函数时,会创建一个包含this、arguments以及其他命名参数的值来初始化函数的活动对象。然而在函数内部定义的匿名函数,当它返回时,他的作用域链会被初始化为包含Foo函数的活动变量和全局变量对象。更为重要的是,Foo函数执行完毕后,其执行环境的作用域链会被销毁,但它的活动对象不会被销毁,因为匿名函数仍然在引用这个活动变量,直到匿名函数被销毁后,Foo函数的活动对象才会被销毁。

副作用

        基于作用域链的机制,使用闭包也会存在副作用,即闭包只能取得包含函数中的任何变量的最后一个值(尤其是在使用循环语句的时候特别要注意)因为闭包保存的整个变量对象,而不是某个特殊时刻的变量。详见下面例子

function createFun(){
	var result = [];
	for(var i=0;i<10;i++){
		result[i] = function () {
			return i;
		}
	}
	return result;
}
var test = createFun(); 
test[0](); // 10

上面的例子,从表面上看每个函数都会返回自己的索引值,即位置0的函数返回0,位置1的函数返回1,但实际每个函数都返回10。因为每个函数的作用域链中都保存着createFun()函数的活动变量,所以他们引用的都是同一个变量 i 。在函数createFun()执行完毕后,变量 i 的值为10,此时每个函数都引用着保存变量 i 的同一个活动变量,所以每个函数内部 i 的值都是10。

我们可创建另一个立即执行的匿名函数,利用闭包的另一作用:将函数内部的变量始终保存在内存中。使得强制返回每一时刻的变量的值。

function createFun(){
	var result = [];
	for(var i=0;i<10;i++){
		result[i] = function (num) {
			return function(){
				return num;
			};
		}(i);
	}
	return result;
}
createFun()[0]();   // 0

在上面的版本中,我们没有直接把闭包赋值给 result 数组,而是定义了一个匿名函数,并将立即执行该匿名函数的结果赋值给result 数组。而匿名函数有一个参数num,也就是最终要返回的值,在调用匿名函数的时候,我们将传入变量 i,由于函数参数是按值传递的,所以会将变量 i 的当前值赋值给参数 num。而在这个匿名函数内部,有创建并返回了一个可以访问num的闭包。这样一来,result 数组中的每个函数都有自己 num 变量的副本,因此可以返回不同的数值。

当然因为闭包在使用的时候会访问函数的内部作用域,导致函数的内部变量被引用,从而无法被GC机制回收,占用的内存也比普通函数要多,所以闭包不在使用时,要及时释放,将引用内层函数对象的变量赋值为null。

 

 

以上只是我个人的粗浅理解,如有不对,欢迎指正。详细的大家看可参看MDN上的文档,下附链接地址:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

  • 5
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值