标签:
闭包和原型是javascript语言的两大特点,上篇博文《浅析JavaScript原型》中已经总结了原型 ,今天就总结一下闭包的相关知识。
在开始闭包之前,需要先介绍一下匿名函数和JavaScript垃圾回收机制这两个概念。
匿名函数,很容易理解,就是没有名字的函数。
//普通函数 function box(){ return ‘This's just a test’; } //匿名函数的架构思想,但是这样写会报错 function (){ return ‘This's just a test’; } //1.通过表达式自我执行 //形式()(),第一个()放匿名函数,第二个()表示执行和传参 (function (){ alert(‘This's just a test’) ; })(); //2.把匿名函数复制给变量 var test=function (){ return ‘This's just a test’; } alert(test); //function (){return ‘This's just a test’;} alert(test()); //调用方式和函数调用相似
在Javascript中,如果一个对象不再被引用,那么这个对象就会被GC回收。如果两个对象互相引用,而不再被第3者所引用,那么这两个互相引用的对象也会被回收。但是如果函数a被b引用,b又被a外的c引用,那么函数a执行后不会被回收。
好了,对匿名函数和垃圾回收机制有了了解之后接下来就看一下什么是闭包。
闭包是可以访问一个函数作用域里变量的函数,通俗的讲,闭包就是一个受到保护的变量空间,通过闭包可以返回局部变量。JavaScript中所有的function都是一个闭包,不过一般来说,嵌套的function所产生的闭包更为强大,也是大部分时候我们所谓的“闭包”:即在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量。主要应用闭包场合主要是为了:设计私有的方法和变量。
一般创建形式:当function里嵌套function时,内部的function可以访问外部function里的变量,加上return的是内部function时,就是一个闭包。
//外层函数a function a(){ //临时变量i var i = 0; //内层函数b function b(){ //引用外层临时变量i alert(++i); } //执行结果,返回内层函数b return b; } //执行外层函数a,同时给c一个指向内层函数b的引用 var c = a(); //执行内层函数,由于闭包的缘故,函数b中i仍然引用的是外部的临时变量i alert(c();)
在闭包中一般会将内部函数声明为匿名函数,函数a()的等价形式
//外层函数a function a(){ //临时变量i var i = 0; //返回内层函数 return function { //引用外层临时变量i alert(++i); } }
在执行过程中,内部函数引用了函数a()的私有变量,因此函数a执行后不会被回收。
1.不增加额外的全局变量。闭包可以把局部变量驻留在内存中,可以避免使用全局变量。
我们知道如果变量声明不加上var关键字,则默认为全局变量,这样会带来很多麻烦。比如:其他函数可能误用这些变量;造成命名冲突、全局对象过于庞大,影响访问速度等等。
2.保护函数内的变量安全,加强了封装性
3.在内存中维持一个变量(用的太多就变成了缺点,占内存)
1.常驻内存会增大内存使用量,使用不当很容易造成内存泄露。解决方法是在退出函数之前,将不使用的局部变量全部删除。
2.闭包会在父函数外部,改变父函数内部变量的值。所以,如果把父函数当作对象,闭包当作它的公用方法,内部变量当作它的私有属性,这时一定不要随便改变父函数内部变量的值。
缺点一解决实例
function box{ var myDiv=document.getElementById('test'); var text=myDiv.innerHTML; myDiv.onclick=function(){ alert(text); }; myDiv=null //解除引用 }
在研究闭包的时候,旁边一位大牛解释道:我们用的命名空间就是闭包。吗现在回想一下,确实,而且特别形象!通过闭包我们可以访问某些特定作用域内的一些私有变量,而且可以起到缓存的作用,这不就是我们熟知的命名空间么?
标签:
原文地址:http://blog.csdn.net/u010773667/article/details/43834239