学习总结 javascript 闭包
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:
这里的写法攻克了參数变量不能被保存的问题,仅仅要创建一个本地作用域一个变量来接收这个參数变量的值就能够了。
能够说明不同的作用域,互相不影响。
*/