js for循环中的i使用var和let有什么区别?

简介: js for循环中的i使用var和let有什么区别?

目录


先来个简单的测试


  for (var i = 0; i < but.length; i++) {
      console.log(i)//0 1 2
  }
  for (let i = 0; i < but.length; i++) {
    console.log(i)//0 1 2
  }

会发现var和let作为循环的执行输出貌似没什么问题。

是不是就没有区别呢?

当然不是!

变量提升


  1. 相信很多人都知道var有变量提升的问题
  2. 我们猜想如果var导致i提升了,那么用var声明的i会成为window全局的变量。
  for (var i = 0; i < but.length; i++) {
    console.log(i)//0 1 2
  }

代码就相当于i提升到了全局上,循环时用的都是同一个window.i的值

  var i //window.i
  for (i = 0; i < but.length; i++) {
    console.log(i)//0 1 2
    console.log(window.i)//0 1 2
  }
  console.log(i)//3


我们可以做个对照,let声明的i拥有了自己的块级作用域,每次循环的i只在当前循环有效,第一次声明i=0、第二次i=1、。

  for (let i = 0; i < but.length; i++) {
    console.log(i)// 0 1 2
    console.log(window.i)//undefined undefined undefined
  }
  console.log(i)//undefined

问题场景



给按钮添加事件,我们希望按钮输出自己的下标值i和它的内容值。


结果是点击什么都是3,因为var声明的i不具备块级作用域,这里点击事件中的i读取不到这个for循环中的i,只能获取到window上的i,而这个i是最后的值,也就是跳出for循环的but.length,为3。

<body>
    <button>0</button>
    <button>1</button>
    <button>2</button>
</body>
<script>
  const but = document.getElementsByTagName('button')
  for (var i = 0; i < but.length; i++) {
    but[i].onclick = () => {
      console.log('点击的button的下标:' + i)//3 3 3 
    }
  }
</script>

换成let试试

<body>
    <button>1</button>
    <button>2</button>
    <button>3</button>
</body>
<script>
  const but = document.getElementsByTagName('button')
  for (let i = 0; i < but.length; i++) {
    but[i].onclick = () => {
      console.log('点击的button的下标:' + i)//0 1 2
    }
  }
</script>


相关文章
|
8月前
|
JavaScript 前端开发 安全
【JavaScript】深入理解 let、var 和 const
掌握这些关键字的使用可以提高代码的可读性和可维护性,避免潜在的变量提升和作用域问题。希望本文能帮助您更好地理解和应用 JavaScript 中的变量声明方式,编写出更高质量的代码。
199 20
|
9月前
|
JavaScript 前端开发 容器
this、self、window、top 在 JavaScript 中的区别深入研究
在 JavaScript 开发中,`this`、`self`、`window` 和 `top` 是四个常用的概念。`this` 指向当前执行上下文的对象,其值取决于函数调用方式;`self` 在全局作用域中等同于 `window`,常用于 Web Workers;`window` 代表浏览器窗口,是全局变量的容器;`top` 指向最顶层窗口,用于判断是否在框架中。理解这些概念有助于编写健壮的代码。
255 1
this、self、window、top 在 JavaScript 中的区别深入研究
|
7月前
|
移动开发 运维 供应链
通过array.some()实现权限检查、表单验证、库存管理、内容审查和数据处理;js数组元素检查的方法,some()的使用详解,array.some与array.every的区别(附实际应用代码)
array.some()可以用来权限检查、表单验证、库存管理、内容审查和数据处理等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
7月前
|
供应链 JavaScript 前端开发
通过array.every()实现数据验证、权限检查和一致性检查;js数组元素检查的方法,every()的使用详解,array.some与array.every的区别(附实际应用代码)
array.every()可以用来数据验证、权限检查、一致性检查等数据校验工作,核心在于利用其短路机制,速度更快,节约性能。 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
|
7月前
|
消息中间件 JavaScript 前端开发
最细最有条理解析:事件循环(消息循环)是什么?为什么JS需要异步
度一教育的袁进老师谈到他的理解:单线程是异步产生的原因,事件循环是异步的实现方式。 本质是因为渲染进程因为计算机图形学的限制,只能是单线程。所以需要“异步”这个技术思想来解决页面阻塞的问题,而“事件循环”是实现“异步”这个技术思想的最主要的技术手段。 但事件循环并不是全部的技术手段,比如Promise,虽然受事件循环管理,但是如果没有事件循环,单一Promise依然能实现异步不是吗? 博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您
|
11月前
|
JavaScript 前端开发 安全
ECMAScript 6(以下简称 ES6)的出现为 JavaScript 带来了许多新的特性和改进,其中 let 和 const 是两个非常重要的关键字。
ES6 引入了 `let` 和 `const` 关键字,为 JavaScript 的变量管理带来了革新。`let` 提供了块级作用域和暂存死区特性,避免变量污染,增强代码可读性和安全性;`const` 用于声明不可重新赋值的常量,但允许对象和数组的内部修改。两者在循环、函数内部及复杂项目中广泛应用,有助于实现不可变数据结构,提升代码质量。
146 5
|
11月前
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
182 1
|
11月前
|
设计模式 JavaScript 前端开发
js中new和object.creat区别
【10月更文挑战第29天】`new` 关键字和 `Object.create()` 方法在创建对象的方式、原型链继承、属性初始化以及适用场景等方面都存在差异。在实际开发中,需要根据具体的需求和设计模式来选择合适的方法来创建对象。
|
JavaScript 前端开发 PHP
JavaScript中var关键字的使用详解
这篇文章主要介绍了JavaScript中var关键字的使用,是JavaScript入门学习中的基础知识
204 0

热门文章

最新文章