学习地址 :http://stackoverflow.com/questions/111102/how-do-javascript-closures-work
1,关于闭包的简单实现
//example 1
function sayHello(name) {
var words = "hello," + name;
var sayForAlert = function () {
alert(words);
}
sayForAlert();
}
//sayHello("jack");
/*
An Example of a Closure
Two one sentence summaries:
a closure is the local variables for a function — kept alive after the function has returned, or
a closure is a stack-frame which is not deallocated when the function returns (as if a ‘stack-frame‘ were malloc‘ed instead of being on the stack!).
*/
function sayHello2(name){
var words = "hello, "+name; //local variables;
var sayForAlert = function (){
alert(words);
}
return sayForAlert;
}
var say2 = sayHello2("lucy");
say2();
/*
一个函数的引用,作为一个参数返回回来。在这里相当于返回一个函数的
指针。sayForAlert 和 say2指向的是同一函数。
javascrip与c的一个重要区别在于c指针指向一个函数,而javascript是一个引用指向一个函数。(相当于是隐藏性指针)。
在许多的语言中和c一样,当函数执行完成后,本地的变量就不能再访问。
因为其函数的堆栈被销毁。
在javascript中函数的里面可以在声明函数。并且本地的变量可以访问,并
可心在声明的函数中返回。
*/
function saynumadd(){
var num = 666;
var showAlert = function(){
alert(num);
//num++;//place 2;
}
num++;//place 1;
return showAlert;
}
var sayNumber = saynumadd();
sayNumber();//alert 667;
/*
note: 根据上面的执行结果来看num做为一个变量被保存起来在后面
函数的调用可以再获取到。 如果我们把num++;放到place2的位置
看到的结果就是666.说明函数的执行顺序执行 saynumadd() 执行过程
中 1,声明变量num,2,声明函数 showAlert,3,把变量num自增加1;
当我们执行 sayNumber()的时候看到的就是667 增加后被保存的结果。
*/
function setupSomeGlobals(){
var num = 666;
//store some references to function as global variables
getAlertNumber = function (){
alert(num);
}
getIncreaseNumber = function(){
num ++;
}
getSetNumber = function(x){
num = x;
}
}
setupSomeGlobals();
getIncreaseNumber();
getAlertNumber();
getSetNumber(10);
getAlertNumber();//10
setupSomeGlobals();
getAlertNumber();//666
/*
onte:
从上面的例子可以看出,
setupSomeGlobals 里面的三个函数被声明都有权限去访问里面的变量。
如果我们重新调用 setupSomeGlobals() 新的函数堆栈会被创建. 之前创建的getAlertNumber, getIncreaseNumber, getSetNumber 会被重写并有一个新的闭包. (在 JavaScript中, 无论任何候都可以在function的内部声明另外一个function,外面的function被调用的时候,里面的function都会被重新创建.)
*/
function buildList( list ){
var result = [];
for (var i = 0 ; i<list.length; i ++){
var item = ‘item‘ + list[i];
result.push(function(){alert(item +‘ ‘+list[i])});
}
return result;
}
function testList(){
var fnList = buildList([1,2,3,4]);
for(var j=0; j < fnList.length; j ++){
fnList[j]();
}
}
testList();//alert item1 undefined;
/*
运行结果,可以说明function里面的function只可以保存本地变量,不能保存参数变量。所以我们在使用封包函数要注意其中变量的作用域。
*/
function callLocalVar(){
var sayAlertName = function(){alert(name)};
var name = "jacy";
return sayAlertName;
}
callLocalVar()();//这种写首先会执行callLocalVar再执行返回的sayAlertName;
/*
note:
总结闭包函数可以访问到同一个域时定义的变量,无论是在这个闭包函数的前面还是后面。 只要是同一个域就可以被访问到。
*/
function checkClosure(someNum, someRef){
var num = someNum;
var arr = [1,2,3];
var ref = someRef;
return function(x){
num += x;
arr.push(num);
alert(‘num :‘+num + ‘ \n arr :‘+arr.toString()
+‘\n ref.someVar‘+ref.someVar);
}
}
var obj = {someVar:4};
var fn1 = checkClosure(4,obj);
var fn2 = checkClosure(5,obj);
fn1(1);// num: 5; arr: 1,2,3,5; ref.someVar: 4;
fn2(1);// num: 6; arr: 1,2,3,6; ref.someVar: 4;
obj.someVar ++;
fn1(2);// num: 7; arr: 1,2,3,5,7; ref.someVar: 5;
fn2(2);//num: 8; arr: 1,2,3,6,8; ref.someVar: 5;
/*
note:
这里的写法解决了参数变量不能被保存的问题,只要创建一个本地作用域一个变量来接收这个参数变量的值就可以了。
可以说明不同的作用域,互相不影响。
*/
版权声明:本文为博主原创文章,未经博主允许不得转载。