关于JS中for循环时,作用域问题和this指针指向的总结

在大多数计算机语言中,{}这样一对花括弧叫一个块级作用域,也就是一个执行环境。在一个执行环境中,执行环境内部的变量在作用域外部式无法被访问到的。执行环境内部倒是可以访问外部的变量。
但由于JS中没有块级作用域,只有函数作用域。所以类似于像for(;;){ }这样的作用域,实际上它还是在它的上层作用域之内,如果它上层作用域是global或window,那么实际上这个for循环还是在全局作用域下。

所以,在典型的JS面试题中出现的例子:

const Greeters = []  
for (var i = 0 ; i < 10 ; i++) {  
  Greeters.push(function () { return console.log(i) })  
}  
Greeters[0]() // 10  
Greeters[1]() // 10  
Greeters[2]() // 10复制代码

由于,此处默认for语句是在全局作用域下,且for循环并不会生成块级作用域,因此,var声明的i变量也就自然在全局作用域之下,在for循环中又出现了一个匿名函数,这个匿名函数倒是有自己的函数作用域。所以,事实上,这个匿名函数先是写好放在那里,还没有被外部声明调用,它就仅仅地待在那里,当外部声明一个Greeters0想要调用这个函数作时,由于i是在全局作用域被var声明出来的,i已经事先被fior语句循环到等于10了,i=10已经事先固定地保存在全局作用域之中不动了。程序再才来调用的这个函数内部的i。这时,函数只需要去全局作用域环境去找到那个事先已经被固定下来的i=10的那个i就行了,所以,无论调用多少次,它只会去调用那个事先已经循环完毕,并被放入全局作用域下i=10那个i。换句话说,for循环语句的那个{}相当于可以视为没有写。

那么如何解决这个问题呢?

又因为JS中var来声明变量时,var声明出来的变量是在当前作用域环境之下, let声明出来的变量也是在当前作用域之下。不一样的是:let可以把类似于这种JS里面不是块级作用域的作用域(例如for(;;){})变成一个块级作用域,而var不会。并且var可以多次声明同一个变量名,而let不行

var a = 5;   
var a = 3;  
let b = 2;   
let b = 4;  
console.console.log(a);  
console.console.log(b); // Identifier 'b' has already been declared复制代码

所以,我们可以用ES6的语法let来创建一个块级作用域。

const Greeters = []  
for (let i = 0 ; i < 10 ; i++) {  
  Greeters.push(function () { return console.log(i) })  
}  
Greeters[0]() // 0  
Greeters[1]() // 1  
Greeters[2]() // 2复制代码

此时,从外部去调用由于用let每创建一个i,就会去执行一遍内部的匿名函数,并保存起来push进数组Greeters[]里,当你想要调用某一个数组里的函数时,就直接Greetersi 调用对应的数组函数并console.log出当前的i了。

转载于:https://juejin.im/post/59c14d24f265da0672283a75

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值