扫描打开手机站
随时逛,更方便!
当前位置:首页 > 百科 > 帮手

javascript中的闭包中的闭包

时间:2023-10-18 来源:互联网 作者:鹏宇

javascript中的闭包中的闭包

非常抽象的一个概念,我自己的一个理解是:当一个变量(就像上面的name)既不是该函数内部的局部变量,也不是该函数的参数,相对于作用域来说,就是一个自由变量(引用了外部变量),这样就会形成一个闭包.怎么说呢?我们再来看看一开始我们使用的demo

let count = 500; //全局作用域function foo1() {  let count = 0; //函数全局作用域  function foo2() {    let count2 = 1; //随便新增一个变量    // count++;  注释    debugger;    //console.log(count); 注释    //return count;  注释  }  return foo2; //返回函数}let result = foo1();result(); //结果为1result(); //结果为2

再次使用浏览器看看,这时我们就发现Closure已经消失了,这也就证实我说的,如果函数内部不调用外部的变量,就不会形成闭包.但是如果调用了外部变量,那么就会形成闭包. 这也就是说不是所有的函数嵌套函数都能形成闭包

最后我们再来看一个循环闭包的例子

for (var i = 1; i <= 5; i++) {  setTimeout(function timer() {    debugger;    console.log(i); // 输出什么?     }, 1000);}

答案 6 6 6 6 6 .因为setTimeout里面的回调函数是一个异步的过程(异步代表可以不用等待我这个代码先执行完,可以先往后执行),而for循环是同步的(代码只能从上往下的执行),立即执行,异步的setTimeout必须等待一秒才能执行,这时i早已经循环结束了.解决办法有三个:

将for循环中的var 改成let

for (let i = 1; i <= 5; i++) {  setTimeout(function timer() {    debugger;    console.log(i); // 1 2 3 4 5   }, 1000);}

这样就没有问题了, 因为let是有块级的功能,每一层循环都是独立的,互不影响,所以才能正常输出. 2. 把setTimeout()套上一个function

for (var i = 1; i <= 5; i++) {  log(i); // 1 2 3 4 5}function log(i) {  setTimeout(function timer() {    debugger;    console.log(i);  }, 1000);}

这样同样能够实现这个功能,原理和第一个方法一样,每一个log()都是独立的,互不影响,这样才能有正确的结果,var就是因为没有块级的功能,才会出问题 3. 包装成匿名函数

for (var i = 1; i <= 5; i++) {  (function (i) {    setTimeout(function timer() {      debugger;      console.log(i);    }, 1000);  })(i)}

前面一个(func..)定义函数,后面一个(i)调用,这再JavaScript叫做立即执行函数,其实与第二种方式是一样的,只是写法不一样.

结语


理解JavaScript闭包是一项重要的技能,在面试中也常常会有,这是迈进高级JavaScript工程师的必经之路.

推荐教程: 《js教程》