JS闭包为何物

闭包的定义:有权访问另一个函数作用域内变量的函数都是闭包。

闭包出现的原因:因为js的每一个函数都是独立的(封装性),它可以获取外界信息,但是外界却无法直接看到里面的内容。为了让函数内部的变量被另一个函数所使用,所以出现了闭包。

闭包的本质:闭包就是一个函数引用另外一个函数的变量,因为变量被引用着所以不会被回收,因此可以用来封装一个私有变量。这是优点也是缺点,不必要的闭包只会徒增内存消耗!

举例:

//inc函数访问了fun1函数内的变量n

function fun1(){
	var n=0;
	function inc(){
		n++;
		console.log(n);
	}
	inc();
	inc();
}
fun1();

//输出
[Web浏览器] "1"
[Web浏览器] "2"
function fun2(){
	var n=0;
	this.m=1;
	this.inc=function(){
		n++;
		console.log(n);
	}
}
var f=new fun2();
console.log("n="+f.n);
console.log("m="+f.m);
f.inc();
f.inc();

//输出
[Web浏览器] "n=undefined"
[Web浏览器] "m=1"
[Web浏览器] "1"
[Web浏览器] "2"
function fun3(){
	var n=0;
	this.inc=function(){
		n++;
		console.log(n);
	}
	return inc;  //没有(),注意,函数名只是一个标识(指向函数的指针),而()才是执行函数
}
var f=fun3();
f();  //在此时才执行了inc()
f();

//输出
[Web浏览器] "1"
[Web浏览器] "2"

 以下例子理解函数的执行与否:

//该例子不是闭包

function fun4(){
	var n=0;
	this.inc=function(){
		n++;
		console.log(n);
	}
	return inc();  //有(),则在return的时候就执行了一次函数
}
var f=fun4;
f();
f();

//输出
[Web浏览器] "1"
[Web浏览器] "1"
function fun5(){
	var m=2;
	return m;
}
var f=fun5();
console.log(f);
console.log(f());

//输出
[Web浏览器] "2"
[Web浏览器] "Uncaught TypeError: number is not a function"
function fun6(){
	var m=2;
	return m;
}
var f=fun6;
console.log(f);
console.log(f());

//输出
[Web浏览器] "fun6的定义和函数体"
[Web浏览器] "2"

单纯的一句 var f = function() { alert('Hi'); }; 是不会弹窗的,后面接一句 f(); 才会执行函数内部的代码。

是不是以为自己看懂了?那我们来看看下面这个

function createFunctions(){
    var result = new Array();
    for (var i=0; i < 10; i++){
        result[i] = function(){
            return i;
        };
    }
    return result;
}
var funcs = createFunctions();
for (var i=0; i < funcs.length; i++){
    console.log(funcs[i]());
}

//输出
10个10

和我想象的答案不一样啊。一首凉凉,是哪里出了问题呢,其实只需多一行代码即可看懂

function createFunctions(){
    var result = new Array();
    for (var i=0; i < 10; i++){
    	console.log(i);  //执行createFunctions()时执行了
        result[i] = function(){
    		console.log("i="+i);  //执行createFunctions()的时候没有执行这个
            return i;
        };
    }
    console.log("end_i="+i);  //createFunctions()执行完毕,i=10
    return result;
}
var funcs = createFunctions();  //执行createFunctions(),并且将funcs指向了result
console.log(funcs);  //看看这时候的funcs是什么吧!
for (var i=0; i < funcs.length; i++){
    console.log(i+"--"+funcs[i]());
}

//输出
[Web浏览器] "0"
[Web浏览器] "1"
[Web浏览器] "2"
[Web浏览器] "3"
[Web浏览器] "4"
[Web浏览器] "5"
[Web浏览器] "6"
[Web浏览器] "7"
[Web浏览器] "8"
[Web浏览器] "9"
[Web浏览器] "end_i=10"
[Web浏览器] "function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        },function (){
    		console.log("i="+i);
            return i;
        }"
[Web浏览器] "i=10"
[Web浏览器] "0--10"
[Web浏览器] "i=10"
[Web浏览器] "1--10"
[Web浏览器] "i=10"
[Web浏览器] "2--10"
[Web浏览器] "i=10"
[Web浏览器] "3--10"
[Web浏览器] "i=10"
[Web浏览器] "4--10"
[Web浏览器] "i=10"
[Web浏览器] "5--10"
[Web浏览器] "i=10"
[Web浏览器] "6--10"
[Web浏览器] "i=10"
[Web浏览器] "7--10"
[Web浏览器] "i=10"
[Web浏览器] "8--10"
[Web浏览器] "i=10"
[Web浏览器] "9--10"

上面的代码翻译一下就是

var result = new Array(), i;
result[0] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
result[1] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
...
result[9] = function(){ return i; }; //没执行函数,函数内部不变,不能将函数内的i替换!
i = 10;
funcs = result;
result = null; // 此时result被自动回收了,i还被引用着,所以没有回收

console.log(i); // funcs[0]()就是执行 return i 语句,就是返回10
console.log(i); // funcs[1]()就是执行 return i 语句,就是返回10
...
console.log(i); // funcs[9]()就是执行 return i 语句,就是返回10

 

感谢作者:http://www.cnblogs.com/qieguo/p/5457040.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值