关于闭包的理解

一、闭包的概念

首先来看一个例子

function func1 () {
	var a = 0;
	return function () {
		a++;
		console.log(a);
	}
}
var func2 = func1();
func2();   //1
func2();   //2
func2();   //3

在这个例子中,func2就是一个闭包。

简单来说,闭包是一个函数,它可以在func2的作用域内使用func1的变量。在正常情况下,在执行完func1时,私有变量要被回收。但是上述例子中,返回的func2函数使用了func1的私有变量a,从而使a能够继续存在于内存中,而不被回收。

在使用闭包的过程中,需要理解作用域和生命周期。作用域涉及作用域链,变量对象和活动对象等;生命周期需要理解全局变量,私有变量和垃圾回收机制。

结合例子分析:

var a = 1;
var func1 = function () {
	var b = 2;
	var func2 = function () {
		console.log(b);
	}
	func2();
}
func1();

二、作用域和作用域链,变量对象,活动对象

作用域:变量a的作用域是全局,变量b的作用域是func1内部,变量的作用域就是变量的有效范围。

作用域链:当执行func1时,会创建func1的执行环境,并把这个对象置于链表开头;当执行func2时,也会创建func2的执行环境,把对象置于链表开头。

因此形成作用域链:func2—func1—window

变量对象:存储了上下文中定义的变量和函数声明。

活动对象:变量对象的子集,它存储的则是被调用函数中的变量和函数声明。例如执行func2时,变量对象是a,func1,b,func2,活动对象为b,func2。

三、生命周期,全局变量,局部变量,垃圾回收

生命周期:a是全局变量,它的生命周期是直到关闭页面;b是局部变量,它在函数内部定义,退出函数时,b就会被回收。

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

垃圾回收机制有标记清除和引用计数两种。

标记清除:常用,当变量进入到环境,则标记为“进入环境”,此时的变量是有可能用到的,所以不能清除;当变量离开环境,则标记为“离开环境”,此时变量没有用,则清除并且释放内存。

function func1 () {
	var a = 1;   //标记进入环境
	var b = 2;   //标记进入环境
}

引用计数:跟踪记录每个值被引用的次数。当声明了一个变量,并且把一个引用类型赋值给变量,那么这个值的引用次数+1;如果改变了又取得了另外一个值,那么之前的值的引用次数-1,如果该值的引用次数为0,那么就没有办法访问到这个值,则释放内存。

var str1 = 'aaa';   //'aaa'的引用次数为1
str1 = 'bbb';       //'aaa'的引用次数-1,最后为0

引用计数可能引发内存泄漏

function func1 () {
	var a = {};
	var b = {};

	a.c = b;
	b.c = a;
}

a,b的引用次数都是2,即是退出了函数func1,a,b也不能被回收。如果存在大量这种情况,则会造成内存泄漏。IE7和IE8中的DOM回收使用的就是引用计数。

可以通过以下方法来解决

a.c = null;
b.c = null;

四、关于闭包的一个例子

例一:按顺序弹出0,1,2,3,4

for (var i = 0; i < 5; i++) {
	alert(i);    //alert的执行是同步的,所以每次循环都会按顺序执行
}

例二:
预期效果:每隔2s,弹出一个数字
实际效果:2s后依次连续弹出5,5,5,5,5

原因:setTimeout是异步操作,在执行setTimeout前已经执行完i++,因此执行setTimeout时,查询i的值一直为5。

for (var i = 0; i < 5; i++) {
	setTimeout(function () {
		alert(i);
	}, 2000)
}

例三:

实际效果:2秒后弹出0,1,2,4,3(顺序不定)

for (var i = 0; i < 5; i++) {
	(function (i) {   //将每次循环的i封闭起来,但是耶由于set Timeout是异步操作,因此五次循环都是2秒后执行,执行顺序有差异
		setTimeout(function () {
			alert(i);
		}, 2000)
	})(i)
}

参考:

《JavaScript设计模式与开发实践》--曾探

猜你喜欢

转载自blog.csdn.net/zhongshanxian/article/details/80981939