前端面试必问——JS中的闭包是什么?

一、什么是闭包?

先说概念:

闭包是指有权访问另一个函数作用域中变量的函数。

创建闭包的最常用的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域,将函数内部的变量和方法传递到外部。

 

二、关于闭包概念的理解

从概念中可以看出,要形成闭包有2个不可或缺的关键因素,分别是:

      ①1个函数   ②函数内部可以访问的变量

比如:

var num = 665;
function sayAlert(){
    alert(num);
}

(在上述例子中,num就是1个变量,而sayAlert则是一个函数,在该函数中可以访问num这个变量。)

 

紧接着把这几句代码放到一个立即执行函数中,再return该函数,如下所示:

function say666() {
   var num = 665;
   function sayAlert() {
       alert(num);
   }
   num++;
   return sayAlert;
}

var sayAlert = say666();
sayAlert();  //执行结果为弹出666

在上述例子中,sayAlert函数和num变量就形成了闭包。

可以看出有两个问题:

一、为什么需要函数嵌套函数?

函数嵌套函数是为了让变量成为局部变量,比如在上述例子中num就成为了局部变量,如果不嵌套直接写在外面就成为了全局变量。

所以,函数套函数就是为了制造出一个局部变量。

二、为什么需要return函数?

return函数就是为了让这个函数可以被使用,在上述例子中return sayAlert就是为了让这个函数在外部可以被使用。

 

解决了上述两个问题后,又有一个问题出现了:

为什么要让变量成为局部变量呢?

我想这个问题有好几个答案,首先是局部变量可以一直被保存在内存中,不会被垃圾回收机制回收。还有就是可以通过闭包来隐藏一个变量,比如在上述例子中我们也完全可以让num成为一个全局变量,但是我又不想让num这个变量的值被任何人任意更改(不想让别人直接访问到这个变量),所以我们可以让它成为局部变量,并且暴露一个函数,让他人可以间接访问。

三、分享一个闭包使用案例

最后给大家分享一个闭包的使用案例,使用闭包让 4个li节点的onclick事件都能正确的弹出当前被点击的li索引

 

  • index =0
  • index =1
  • index =2
  • index =3

在上述例子中,return后的函数和变量i就形成了闭包,如果不使用闭包直接打印的话,那么不管点击哪个li打印出来的值都是4。

大家可以自行尝试。

四、一道面试题

function Foo(){
     var i=0;
     return function(){
         document.write(i++);
     }
}
var f1=Foo(),
f2=Foo();
f1();
f1();
f2();

 上述代码,最后输出的结果是?

 

答案是:0,1,0

这道题就是使用了闭包,它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。 

这里的局部变量i,对f1()来说是全局变量,对f2()来说也是全局变量,但是f1()的i跟f2()的i又是相互独立相互不可见的,闭包被引用的变量不会被释放,f1()每执行一次,f1()的i就加1,f2()每次执行一次,f2()的i就加1,但是相互之间不影响,因此结果是010.


有任何问题欢迎在留言区指出和讨论(✿◕‿◕✿)

你可能感兴趣的:(#,js,前端)