关于javascript闭包的最通俗易懂的理解
这两天在研究闭包,网上一通找,有牛人写的帖子,有普通人写的帖子,但是大多没戳中本小白所纠结的点,而且大多插入了立即执行函数,其实根本不需要的,反而让人产生了误解。这里我用我的方式讲解一下闭包。
1.目的:保证局部变量常驻在内存中,且只能通过固定的方式访问,不可以被所有人访问,算起来也算是个只能被指定对象访问的专用型全局变量。
2.实现方式:在函数f1中返回一个内部定义的函数f2,后通过使用返回出来的函数f2来操作f1中定义的局部变量。
下面我来从各种***钻的角度来举例详细说明,包学包会!看完例子以后再看上面说的目的和实现方式就会有种豁然开朗的感觉了!
round 1:
function add() { var x = 0; return function () { return ++x; } }; /*此处的add()的括号和function add()的括号表达的意思是完全不同的, 在此处add表示上 面定义的函数,add()表示执行一次上面定义的函 数,这一点很关键!执行一次的结果就是返回了函数 function () {return ++x;},但是请注意!这里返回的仅仅是函数本 身,也就是此时函数尚未执行,故此时x=0*/ var temp=add(); //执行一次返回的函数,++x,此时x=1 temp(); //再次执行一次返回的函数,此时x=2,且输出了函数的返回值2,可以在控制台中看到 console.log(temp());
这就完成了闭包了,add函数中的x常驻内存,且我可以在add函数外部通过调用它返回的函数来操作这个x,如果看懂了下面可以不看,如果看了其他帖子有一些其他的异或比如立即执行函数之类的可以看看下面的,你很快就不会疑惑了!
round 2:
//此处temp表示函数add函数本身,但是尚未执行。 var temp = function add() { var x = 0; return function () { return ++x; } }; //执行temp函数,返回函数 function () {return ++x;},但尚未执行该函数,故x=0 var temp1 = temp(); //执行temp1,此时执行了一次function () {return ++x;},故x=1 temp1(); //再次执行一次function () {return ++x;},此时x=2,且输出到了控制台 console.log(temp1());
这一回合是为下面的立即执行函数做铺垫,下面立即执行函数版本隆重登场!当当当当!
round 3:
/*仔细看,此处为(fucntion add(){})(),此处执行了立即执行函数,也就是说返回给temp的与round2返回的add函数本身不同,而是返回的 function () {return ++x;}*/ var temp = (function add() { var x = 0; return function () { return ++x; } })(); //顺理成章的,这里直接执行temp,就是执行了function () {return ++x;},故x=1 temp(); //同理x=2 console.log(temp());
经过上面三个例子的讲解想必你已经心中有数了,但是肯定还是存在疑惑的,比如说round1中var temp=add();,我不把add()的结果赋给temp直接执行行不行?答案是否定的,有一点一定要认知清楚,函数是对象,这一点至关重要,否则将会走入误区。下面举例说明:
这个是round1的改版:
function add() { var x = 0; return function () { return ++x; } }; console.log(add()());//输出1 console.log(add()());//输出1
为什么会这样呢?关键点在于函数是对象,上面实行了两次add()(),在这两次中,add()返回的对象是不一样的,所以他们各自再执行add()()就是为各自的局部变量x加1,所以才两次都输出1,假如改一下
function add() { var x = 0; return function () { return ++x; } }; var temp1 = add(); var temp2 = add(); console.log(temp1());//输出1 console.log(temp1());//输出2 console.log(temp2());//输出1 console.log(temp2());//输出2
这样是不是就明白了,同理add函数也不能写成下面这种形式:
function add() { var x = 0; return (function () { return ++x; })() };
否则返回的只是一个常量而不是一个对象了。希望这篇文章能给跟我一样在摸索闭包的小白一点启发,嘿嘿嘿