http://www.cnblogs.com/jianghua/archive/2012/05/10/2493842.html
最常见的:
用匿名函数:
1 var foo = function () { 2 alert('hi, js'); 3 } 4 foo();
改装一下,给调用的foo()加个括号:
1 var foo = function () { 2 alert('hi, js'); 3 } 4 (foo)();
干脆,连foo的定义也省掉------把foo赋值语句的等号右边的东东、直接替换掉刚才括起来的foo:
1 (function () { 2 alert('hi, js'); 3 })();
先看常用的函数:
闭包的例子
一句话描述:
- 闭包是函数的局部变量,在函数return之后,仍然有值, 或者
- 闭包是stack-frame,在函数return的时候,它不会被释放。(就好像'stack-frame'是内存分配、而非处于堆栈!)
下面的代码返回一个function的引用:
1 function sayHello2(name) { 2 var text = 'Hello ' + name; // local variable 3 var sayAlert = function() { alert(text); } 4 return sayAlert; 5 } 6 var say2 = sayHello2('Jane'); 7 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保存在内存。
1 function say667() { 2 // Local variable that ends up within closure 3 var num = 666; 4 var sayAlert = function() { alert(num); } 5 num++; 6 return sayAlert; 7 } 8 var sayNumba = say667(); 9 sayNumba(); //667,而不是666 10 alert(sayNumba.toString());
Example 4
三个函数对某个闭包使用同一个引用,因为它们均在setupSomeGlobals()里声明的。
1 var gAlertNumber = gIncreaseNumber = gSetNumber = null; 2 function setupSomeGlobals() { 3 // Local variable that ends up within closure 4 var num = 666; 5 // Store some references to functions as global variables 6 gAlertNumber = function() { alert(num); } 7 gIncreaseNumber = function() { num++; } 8 gSetNumber = function(x) { num = x; } 9 } 10 setupSomeGlobals(); 11 //任意、多次 运行下面的函数 12 gAlertNumber(); 13 gIncreaseNumber(); 14 gSetNumber(5); //把num重新设为 5 15 gSetNumber(-8888); //把num重新设为 -8888
重新运行setupSomeGlobals(); 就会重新产生一个新的闭包。在JavaScript中,当你在函数里又声明一个函数,外部函数每调用一次,内部函数将再被重新产生一次。
Example 5
当心下面例子的循环:闭包中的局部变量可能和你最初想的不一样。
1 function buildList(list) { 2 var result = []; 3 for (var i = 0; i < list.length; i++) { 4 var item = 'item' + list[i]; 5 result.push( function() {alert(item + ' ' + list[i])} ); 6 } 7 return result; 8 } 9 10 function testList() { 11 var fnlist = buildList([1,2,3]); 12 // using j only to help prevent confusion - could use i 13 for (var j = 0; j < fnlist.length; j++) { 14 fnlist[j](); 15 } 16 } 17 18 testList(); //输出3次:'item3 undefined'
Example 6
下面的例子表明,闭包包含了 在外部函数退出之前、定义的任何局部变量。注意,变量alice实际上在匿名函数之后声明的。匿名函数先被声明:当函数被调用时,它可以访问alice,因为alice在闭包里。
1 function sayAlice() { 2 var sayAlert = function() { alert(alice); } 3 // Local variable that ends up within closure 4 var alice = 'Hello Alice'; 5 return sayAlert; 6 } 7 sayAlice()(); //Hello Alice 8 alert(alice); //错误:alice不是全局变量,它在函数体内var了
Example 7
下面的例子表明,每次调用会产生各自的闭包。
1 function newClosure(someNum, someRef) { 2 // Local variables that end up within closure 3 var num = someNum; 4 var anArray = [1,2,3]; 5 var ref = someRef; 6 return function(x) { 7 num += x; 8 anArray.push(num); 9 alert('num: ' + num + 10 '\nanArray ' + anArray.toString() + 11 '\nref.someVar ' + ref.someVar); 12 } 13 } 14 closure1 = newClosure(40, {someVar : 'closure 1'}); 15 closure1(5); 16 17 closure2 = newClosure(1000, {someVar : 'closure 2'}); 18 closure2(-10);
小结
读一些说明要比理解上面的例子难得多。我对于闭包的说明以及stack-frame等等在技术上可能不正确 --- 但是它们的确有助于理解
http://blog.sina.com.cn/s/blog_675879000100iju3.html
1、js静态化函数,使用的时候不需要初始化。如下:
var CheckFlash = {
check: function() {
var isIE = (navigator.appVersion.indexOf("MSIE") >= 0);
var hasFlash = true;
if (isIE) {
try {
var objFlash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
} catch (e) {
hasFlash = false;
}
} else {
if (!navigator.plugins["Shockwave Flash"]) {
hasFlash = false;
}
}
return hasFlash;
}
, prompt: function() {
var flag = this.check();
if (!flag) {
window.alert("本页面需要安装9.0以上的flash播放器后才能正常安装!");
}
else {
alert("Y");
}
}
}
使用的时候直接调用即可:window.onload = CheckFlash.prompt();
2、需要初始化得写法
var CheckFlash = function(){};
CheckFlash.prototype={
check: function() {
var isIE = (navigator.appVersion.indexOf("MSIE") >= 0);
var hasFlash = true;
if (isIE) {
try {
var objFlash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash");
} catch (e) {
hasFlash = false;
}
} else {
if (!navigator.plugins["Shockwave Flash"]) {
hasFlash = false;
}
}
return hasFlash;
}
, prompt: function() {
var flag = this.check();
if (!flag) {
window.alert("本页面需要安装9.0以上的flash播放器后才能正常安装!");
}
else {
alert("Y");
}
}
}
调用方法: var c = new CheckFlash();
c.prompt();
两者的优点缺点暂时还不知