闭包和块作用域的交叉使用?

截屏2019-12-0216.48.09.png

把let换成var有这么大的区别是为什么呢?

阅读 1.9k
3 个回答

因为下边通过var声明的变量i在不同块级作用域内是同一个,上边的let声明的i,在每个块级作用域内都是独立的

其实这里的唯一差别就是var和let。

二者从用法上来说除了作用域之外别无二致。

对于var来说,他是函数作用域或者全局作用域。 这个取决于var所处的为止,如果在函数内部声明就是函数作用域,如果在全局声明就是全局作用域。

对于let来说,他是块作用域。 它是为数不多的块作用域,其他也有 比如 const 或者 try catch中的 catch中的变量也是块作用域. 和var不同,let定义的变量会”附着“在最近的block,而不是“附着”在最近的函数和script。

对于你这个题来说,let的声明会”附着“在for 的 {} 内部。 而且由于是for, 上述例子其实会声明5个完全不同的变量,尽管变量的名字都是i(就好像函数a里可以有一个i,同时函数b也可以有一个i,互不干扰)。 并且5个变量实际上对应的是不同的值。 而对于var,由于会“附着”到最近的函数或者script,因此实际上只有一个变量,一个变量当然只能有一个值,而不是5个。

That's all the diffrences

这是个块级作用域的问题。for循环中的var声明变量作用域是会溢出到循环体外的,比如

// 第一次循环
var i = 1
if (i <= 5) {
   // 执行代码,此时的i是1
   i++
}

// 第二次循环
var i = 2
if (i <= 5) {
    // 执行代码,此时的i是2
    i++
}
...

可想而知,当第五次循环结束,i的值会变成6,异步回调中的变量会全部变成6,因为循环了5次,所以回调函数执行5次
再来看let声明的变量,它是存在于作用域中,不会消失的,就能得到你想要的依次打印1,2,3,4,5这样的结果。你可以仔细看看阮一峰老师关于let和const命令这章

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题