码迷,mamicode.com
首页 > 编程语言 > 详细

JavaScript中的闭包

时间:2015-05-04 17:24:03      阅读:132      评论:0      收藏:0      [点我收藏+]

标签:

/**
 * 闭包是个专业词汇,这样才能显得在js中是高大上的货色,官方定义我这里就不敢修改它,
 * 定义如下:就是有权访问另一个函数作用域的变量的函数。
 */

/**
 * 1、闭包的经典例子
 * 这是一个说闭包原理的经典例子,经典在哪里?
 * 如例子中我使用compare时,我的function是可以访问到createComparison函数中的propertyName字段的,
 * 其实这个理解并不复杂,我们去看看浏览器的scope variables就一清二楚了。
 * 
 */
//比较函数
function createComparison(propertyName) {

	return function(obj1, obj2) {
		var item1 = obj1[propertyName];
		var item2 = obj2[propertyName];

		if (item1 < item2)
			return -1;

		if (item1 > item2)
			return 1;

		if (item1 == item2)
			return 0;
	}
}

// 比较name
var compare = createComparison("name");

var result = compare({
	name : "d",
	age : 20
}, {
	name : "c",
	age : 27
});

技术分享

/**
 * 我们可以清楚的看到,在chrome的本地变量表中清楚的记录着当前执行函数中的本地变量列表,并且还进行了分类,
 * 比如上面的"局部函数变量(Local)"、"包含函数变量(Closure)"、"全局变量(Global)",
 * 那下面有个有趣的问题就来了,chrome怎么知道我代码执行到20行的时候,当前的local variables有哪些呢?
 * 而且还能给我分门别类,是不是太奇葩了????但是仔细推敲一下就能豁然开朗,肯定有一个变量保存着当前的variables,
 * 不然的话,chrome去哪读取呢?对不对????????
 * 
 * 谜底揭晓:
 * 其实在每个function里面都有一个scope属性,当然这个属性被引擎屏蔽了,你是看不见也摸不着的,
 * 它里面就保存着当前函数的 local variables,如果应用到上面demo的话,就是全局函数中有一个scope,
 * createComparison有一个scope,匿名的compare有一个scope,而且这三个scope还是通过链表链接的,
 * 画个简图如下:
 */

技术分享

/**
 * 从上面简图中可以看到,其实整个函数中有三个scope,每个scope都是用next指针链接,这样就形成了一个链表,
 * 当我执行下面代码的时候:
 * var result = compare({ name: "d", age: 20 }, { name: "c", age: 27 });
 * 
 * js引擎会拿到当前compare的scope,通过scope属性的next指针,就可以区分哪些变量属于哪个函数,
 * 这样你就看到了chrome对variables的分门别类了。
 */

2、加深理解

/**
 * 2、加深理解
 * 在这个例子中,我想做一个function()数组的array,并且最后都能输出各自的值(1,2,3,4,5...10),
 * 但是结果又是怎样呢?可以看到下图中输出的其实是10个10。。。这样就违背了我的原始意图。
 * 
 * 这个陷阱的最大问题在于你自以为我在匿名function中写了return i;就认为它是属于匿名函数的,其实这就大错特错了,
 * 因为这个i就算走到天涯海角都不属于匿名函数,而是属于它的包含函数Person,
 * 所以原理应该是这样,比如你看,当我执行arr[0]()的时候,这时候匿名函数就会通过scope去找i,但是在匿名函数
 * 的scope中没有i,所以就通过next找到了Person函数,确实在Person中找到了i,但是这个时候i已经是10了,
 * 然后结束scope查找输出10。
 * 
 * 解决方案也很简单,给每个匿名function一个副本就好了,具体原理我想你应该可以用scope推测出来了,对不对。
 */
var arr = new Array();

function Person() {
    for (var i = 0; i < 10; i++) {

        //要记住,这个属性函数申明,只有立即执行才会取scope属性
        var item = function () {
            return i;
        };

        arr.push(item);
    }
}

Person();

for (var i = 0; i < arr.length; i++) {
    console.log(arr[i]());
}



//将Person()改成如下,就OK了

function Person() {
    for (var i = 0; i < 10; i++) {

        //要记住,这个属性函数申明,只有立即执行才会取scope属性
        var item = function (num) {
            return function(){
            	return num;
            }
        }(i);

        arr.push(item);
    }
}

技术分享 

--改完之后的效果:

技术分享

 

注释:此文来源于http://www.cnblogs.com/huangxincheng/p/4189843.html

JavaScript中的闭包

标签:

原文地址:http://www.cnblogs.com/qiupeng/p/4476593.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!