美文网首页JSweb前端技术分享
67.for循环中的var 和 let

67.for循环中的var 和 let

作者: wo不是黄蓉 | 来源:发表于2022-02-27 22:01 被阅读0次

day16:
这段代码我们应该都见过,想要的效果是我们每隔一秒钟分别打印出来1,2,3,4,5。然而,效果却是打印了5,5,5,5,5。但是我们把声明i的声明语句改成let就可以这是为什么呢?

for (var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i);
  }, i*1000);
}

原因是因为,var声明的变量会被变量提升,上面一段代码相当于

var i;
for (i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i);
  }, i*1000);
}

此时i就是全局对象中的一个属性,即是window下的,因此我们每次修改执行完i的值之后,在异步任务还未执行到的时候for循环已经执行完成了,此时i的值已经被修改成了5,因此每次输出的都是5.
那么为什么使用let就可以解决呢?
因为let声明的变量会存在一个块级作用域的概念,使用let声明迭代变量时,js引擎会在后台为每一个迭代循环声明一个新的迭代变量,因此每次使用的i算是不同的。
如何不使用let来解决var变量作用域相同的问题呢?
使用闭包
产生闭包的条件:

  • 内部函数引用外部的变量
  • 有内部函数
  • 有外部函数
    不会用闭包咋办?
    今天看到一句话,觉得刷新了我对闭包的认知。可以将闭包理解成一个创造函数对象的工厂,不会写闭包的按照此套路真是屡试不爽,哈哈哈
    举个例子:
for (var i = 0; i < 5; i++) {
//2.a的结果时一个函数
  let a = creater();
//3.执行i,此时i的值还未改变,此时另一个函数作用域中引用了i变量的值,因此i并不会就此销毁而是会被延用到a函数这个作用域中
  a(i);
}

//1.creater相当于就是一个工厂函数,用来延长i的作用域
function creater() {
//4.此时参数的i就是a中的i。在创建函数时会创建一个作用域链,此时参数中的i指向的是a中的i,而a中的i又是全局中的i,在函数创建过程中会预装载全局变量对象,并保存到内部的scope中。此时就创建了一个新的空间,因此全局变量的修改就不会影响到i的改变。
  return function (i) {
    setTimeout(() => {
      console.log(i);
    }, i*1000);
  };
}

分析过程看上面代码注释。
何以见得全局变量的修改就不会影响到i的改变?

for (var i = 0; i < 5; i++) {
  let a = creater();
  a(i);
}

console.log(i + " start");
i = 10;
function creater() {
  return function (i) {
    setTimeout(() => {
      console.log(i);
    }, i * 1000);
  };
}
console.log(i + " end");

打印i时,会发现i的值已经改为了10,发现start之前未5,end时是10.说明此时修改的i就是全局变量中的i。

还有一种常见的修改思路:使用IIFE。原理相同不多做分析。

for (var i = 0; i < 5; i++) {
  (function (i) {
    setTimeout(() => {
      console.log(i);
    }, 1000);
  })(i);
  creater(i);
}

相关文章

  • 67.for循环中的var 和 let

    day16:这段代码我们应该都见过,想要的效果是我们每隔一秒钟分别打印出来1,2,3,4,5。然而,效果却是打印了...

  • ES6 let var const解析

    let 和 var,const let声明的变量只在let所在的代码块有效 for循环中,var声明的是全局的,l...

  • ES6 let与const

    let和const let命令 let用法类似var,但是所声明的变凉,只在let命令所在的代码块内有效 for循...

  • 第一章 let和conset命令

    let 1.let声明类似于var,但是let只在所在的代码块中有效,可以很好的用在for循环中代替var,记住只...

  • [转载] for循环中let和var区别

    首先看一段代码: 区别: var是全局作用域,有变量提升的作用,所以在for中定义一个变量,全局可以使用,循环中的...

  • (一)let 和 const 命令

    let命令 let命令声明的变量,只在let所在的块级作用域有效 如果将循环中的let写为var,则arry[3]...

  • 2019-06-12 For循环原理

    For循环原理 我们知道for循环中如果用var定义和用let定义是产生不同的结果的,原因是var是全局定义,le...

  • for循环中var或let和异步的使用

    在for循环中使用var 上面的代码输出两个2,原因是for循环属于同步,setTimeout属于异步,同步代码执...

  • 一、ES6新增特性 let 和const

    1、let命令 let与Var区别: let用户声明变量,但只在所在的代码块内生效,在for循环中使用很是合适;v...

  • ES6学习笔记1

    let命令 let命令声明的变量只在所在代码块内生效,适用于for循环中的变量。经典的闭包问题如果用let来作为循...

网友评论

    本文标题:67.for循环中的var 和 let

    本文链接:https://www.haomeiwen.com/subject/qsxkrrtx.html