面试题(4)之 作用域、闭包、异步

题一

for  (var  i  =  0;  i  <  5;  i++)  {
    setTimeout(function ()  {  console.log(i);  },  i  *  1000 );
  // function为闭包函数
} // 连续4秒,每一秒输出一个5,一共5个5,一开始就输出一个5!!!

这道题涉及到了作用域、闭包、异步

作用域:变量的使用范围

全局作用域:

①函数之外的执行变量

②在全局作用域中用var关键字创建的变量为全局变量

​ ③全局变量的可访问范围是程序的任何地方局部作用域:

①函数体内的执行环境

②在函数体内用var创建的变量或者函数的形参被称为局部变量

​ ③局部变量的可访问范围是仅限于本函数中作用域链​ 在访问一个变量时,会先从本作用于中去找,如没有找到则向上级作用域中去找,以此类推就构成了作用域链

​ 内层作用域可以访问外层作用域,反之不行。

闭包:本质:闭包是有权访问另一个函数作用域中变量的函数其他解释:闭包就是能够读取/设置其他函数内部变量的函数理解:闭包就是将函数内部和函数外部链接起来的一座桥梁

作用:延长变量的生命周期

闭包的用途:可以在函数外部读取函数内部成员让函数内成员始终存活在内存中(延长变量的适用范围)闭包简单来说就是一个函数内部的变量,可以在外部作用域中操作

 

异步:

JavaScript是单线程语言,但它允许通过设置超时值和间歇时间值来调整代码在特定的时刻执行,而settimeout是超时调用,它是异步执行的。

在该例题中,主线程为for循环,每过1s便向任务队列中添加一个settimeout超时调用,此时,settimeout虽然都执行了一次,里面的function则不会执行,被放入任务队列里,放了5次。

当主线程结束时,i为5,这是才去执行异步的settimeout。(for语句的执行速度是瞬间执行完的,所以一开始在打印台就打印一个5)这时,连续4秒,每一秒输出一个5,一共5个5,一开始就输出一个5!

题二

把var变成let,代码如下

for  (let  i  =  0;  i  <  5;  i++)  {
  setTimeout(function ()  {  console.log(i);  },  i  *  1000 );
  // function为闭包函数
}  // 0  1  2  3  4 

题三

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

**分析:分析思路同题二,只不过,每次循环都把i作为实参传到闭包函数中执行了**

原文地址:https://www.cnblogs.com/houfee/p/10419414.html