let vs var in javascript [duplicate]

扶醉桌前 提交于 2020-06-25 13:07:39

问题


I understand that let has block scope and var has functional scope. But I do not understand in this case, how using let will solve the problem

const arr = [1,2,3,4];
for (var i = 0; i < arr.length; i++) {
setTimeout(function() {
   console.log(arr[i]) 
}, 1000);
} // Prints undefined 5 times

const arr = [1,2,3,4];
for (let i = 0; i < arr.length; i++) {
setTimeout(function() {
   console.log(arr[i]) 
}, 1000);
} // Prints all the values correctly

回答1:


First of all, the output will be four times and not five times(as mentioned in your comment). I pasted your code in Babel REPL and this is what I got,

"use strict";

var arr = [1, 2, 3, 4];

var _loop = function _loop(i) {
setTimeout(function () {
   console.log(arr[i]);
}, 1000);
};

for (var i = 0; i < arr.length; i++) {
_loop(i);
}

Do you see how let works internally now? :-)




回答2:


This is all related to the scope of the variable. Let's try to wrap both the pieces into functions, and observe the output:

function test() {
  // `i` will be declared here, making it a non-for-loop scoped variable
  const arr = [1, 2, 3, 4];
  for (var i = 0; i < arr.length; i++) {
    setTimeout(function() {
      console.log(arr[i])
    }, 1000);
  } // Prints undefined 5 times
}

test();

So in the first case, i will be hoisted, and because of the asynchronous nature of setTimeout, i will immediately become 4 as the loop ends without waiting. This will make arr[i] to point to an undefined element in the array.

In the second case, i is not hoisted, and has scoped access to each iteration of the loop, making i accurately available to console.log statement. Thus the results are as per the expectations:

function test() {
  const arr = [1, 2, 3, 4];
  for (let i = 0; i < arr.length; i++) {
    setTimeout(function() {
      console.log(arr[i])
    }, 1000);
  } // Prints all the values correctly

}

test();



回答3:


You can still use var for setTimeout. You can use an immediately-invoked function expression (IIFE) to create a closure around setTimeout such that the value of i is recognised by the setTimeout function.

const arr = [1,2,3,4];
for (var i = 0; i < arr.length; i++) {
(function(i){
setTimeout(function() {
   console.log(arr[i]) 
}, 1000)})(i);
}


来源:https://stackoverflow.com/questions/48002533/let-vs-var-in-javascript

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!