浅谈javascript闭包
什么是闭包,各种专业论文上有很多解释,简单是说就是一种能够读取其它函数内部变量的函数,在javascript的高级应用中经常用到,但是JS中只有函数内部的子函数才能读取此函数的变量,因此在JS中的闭包实际上就是函数内部的函数
function f1(){ var n=999; nAdd=function(){n+=1} function f2(){ alert(n); } return f2; } var result=f1(); result(); // 999 nAdd(); result(); // 1000
上面这个例子,f2就是所谓的闭包,他包含在函数f1里面。
闭包最大的用途有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
例如上面的例子中的f2,它一共运行了两次,第一次的值是999,第二次的值是1000。这证明了,函数f1中的局部变量n一直保存在内存中,并没有在f1调用后被自动清除。
原因在于,f2被赋给了一个全局变量n(实际上n是f1中的变量,但在f2中并不是传递进来的变量,也未声明,而是读取的上级函数的变量,判定为全局变量),这就导致了f2被一直存在内存中,而f2依赖于f1,因此f1也被存于内存中而不被释放,才导致了后面使用result的时候两次值的增加。
这段代码中另一个值得注意的地方,就是"nAdd=function(){n+=1}"这一行,首先在nAdd前面没有使用var关键字,因此nAdd是一个全局变量,而不是局部变量。其次,nAdd的值是一个匿名函数(anonymous function),而这个匿名函数本身也是一个闭包,所以nAdd相当于是一个setter,可以在函数外部对函数内部的局部变量进行操作。</p>
这是从博客园上看到的一个淘宝前端开发面试JavaScript部分一道题。
题目是:下面这个ul,如何点击每一列的时候alert其index值
<ul id=”test”> <li>这是第一条</li> <li>这是第二条</li> <li>这是第三条</li> </ul> <p>
使用js遍历很容易就做出来,同时他给出了一种用闭包解决的方法:
var lis_lis = $("test").getElementsByTagName("li"); for (var i = 0, l = lis_lis.length; i < l; i++) { lis_lis[i].onclick = (function(x) { return function() { alert(x); } })(i); }
这段代码中lis_lis[i].onclick调用了一个闭包函数,这个闭包函数和之前的例子不同的在于它传值i进去了,这个就要考虑到这个的表达式形式,区别而言是给lis_lis[i].onclick赋值的表达式,而之前的例子是函数声明形式的,用法雷同。
下面贴一些例子:
//*************闭包uniqueID************* uniqueID = (function(){ //这个函数的调用对象保存值 var id = 0; //这是私有恒久的那个值 //外层函数返回一个有权访问恒久值的嵌套的函数 //那就是我们保存在变量uniqueID里的嵌套函数. return function(){return id++;}; //返回,自加. })(); //在定义后调用外层函数. document.writeln(uniqueID()); //0 document.writeln(uniqueID()); //1 document.writeln(uniqueID()); //2 document.writeln(uniqueID()); //3 document.writeln(uniqueID()); //4
//*************闭包阶乘************* var a = (function(n){ if(n<1){ alert("invalid arguments"); return 0; } if(n==1){ return 1; } else{ return n * arguments.callee(n-1); } })(4); document.writeln(a); </pre> <pre lang='javascript' colla='+'> function User( properties ) { //这里一定要声明一个变量来指向当前的instance var objthis = this; for ( var i in properties ) { (function(){ //在闭包内,t每次都是新的,而 properties[i] 的值是for里面的 var t = properties[i]; objthis[ "get" + i ] = function() {return t;}; objthis[ "set" + i ] = function(val) {t = val;}; })(); } } //测试代码 var user = new User({ name: "Bob", age: 44 }); alert( user.getname()); alert( user.getage()); user.setname("Mike"); alert( user.getname()); alert( user.getage()); user.setage( 22 ); alert( user.getname()); alert( user.getage());

浙公网安备 33010602011771号