日期:2014-05-16 浏览次数:20482 次
最常见的:
?
function foo() { alert('hi, js'); } foo();
?
用匿名函数:
var foo = function () { alert('hi, js'); } foo();
?
改装一下,给调用的foo()加个括号:
?
var foo = function () { alert('hi, js'); } (foo)();
?
干脆,连foo的定义也省掉------把foo赋值语句的等号右边的东东、直接替换掉刚才括起来的foo:
(function () { alert('hi, js'); })();
?
?
先看常用的函数:
?
function sayHello(name) { var text = 'Hello ' + name; var sayAlert = function() { alert(text); } sayAlert(); } sayHello('Bob');
?
闭包的例子
?
一句话描述:
下面的代码返回一个function的引用:
?
?
function sayHello2(name) { var text = 'Hello ' + name; // local variable var sayAlert = function() { alert(text); } return sayAlert; } var say2 = sayHello2('Jane'); say2(); //hello Jane
?
?
多数JavaScript程序员能够理解上面代码的函数引用如何返回给变量。请在学习闭包之前理解它。C程序员把函数看做返回的一个函数指针,变量sayAlert和say2分别是函数指针。
C函数指针和JavaScript的函数引用有着本质的不同。在JavaScript,函数引用变量既是一个函数指针,又是一个隐藏的闭包指针。
?
上面代码拥有闭包,因为函数体内又声明了一个匿名函数 function() { alert(text); } ,参看例子中的sayHello2()。如果你在另一个函数内使用function关键字,闭包就产生了。
?
在C和其他多数语言,当函数return之后,stack-frame就被销毁了,所有的局部变量也就不能访问了。
?
在JavaScript中,如果你在函数里声明了函数,在你调用的函数renturn之后,局部变量仍然可以访问。请注意上面的例子,我们调用了变量text,它是函数sayHello2的局部变量。
?
Example 3
?
这个例子表明局部变量不是拷贝传递,而是引用传递。在外层函数退出时,它把stack-frame保存在内存。
?
?
function say667() { // Local variable that ends up within closure var num = 666; var sayAlert = function() { alert(num); } num++; return sayAlert; } var sayNumba = say667(); sayNumba(); //667,而不是666 alert(sayNumba.toString());
?
Example 4
三个函数对某个闭包使用同一个引用,因为它们均在setupSomeGlobals()里声明的。
?
var gAlertNumber = gIncreaseNumber = gSetNumber = null; function setupSomeGlobals() { // Local variable that ends up within closure var num = 666; // Store some references to functions as global variables gAlertNumber = function() { alert(num); } gIncreaseNumber = function() { num++; } gSetNumber = function(x) { num = x; } } setupSomeGlobals(); //任意、多次 运行下面的函数 gAlertNumber(); gIncreaseNumber(); gSetNumber(5); //把num重新设为 5 gSetNumber(-8888); //把num重新设为 -8888
?
重新运行setupSomeGlobals(); 就会重新产生一个新的闭包。在JavaScript中,当你在函数里又声明一个函数,外部函数每调用一次,内部函数将再被重新产生一次。
?
Example 5
?
当心下面例子的循环:闭包中的局部变量可能和你最初想的不一样。
?
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]); // using j only to help prevent confusion - could use i for (var j = 0; j < fnlist.length; j++) { fnlist[j](); } } testList(); //输出3次:'item3 undefined'
?
Example 6
?
下面的例子表明,闭包包含了 在外部函数退出之前、定义的任何局部变量。