这个问题其实是看基础扎不扎实了, 如果理解了var
、let
、const
这三个关键字的区别,那么就能明白为什么这三个for
循环的输出是这样,那么我们先来了解下基础概念:
先谈谈let
和const
吧,var
是js
蛮荒时代的遗留产品。
let
的使用和var
是差不多,和var
的区别是
let
只会在它所声明的块中生效。请看代码:
{
let a = 10;
var b = 1;
}
a // 代码块外访问a 会报错 ReferenceError: a is not defined.
b // 代码块外访问b,可以拿到数据 1
let
不存在变量提升。请看代码
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
在相同作用域内不允许重复声明同一变量。请看代码
// 报错
{
var a = 10;
let a = 10;
}
// 报错
{
let a = 1;
let a = 2;
}
不能在let
变量声前使用(TDZ暂时性死区)。请看代码
{
// TDZ开始
tmp = 'abc'; // 报错: ReferenceError
console.log(tmp); // 报错: ReferenceError
let tmp; // TDZ结束
console.log(tmp); // undefined
tmp = 123;
console.log(tmp); // 123
}
let
声明的变量会绑定当前作用,不受外部变量影响
var tmp = 123;
if (true) {
console.log(tmp) // 报错(触发暂时性死区):ReferenceError
let tmp = 'abc';
console.log(tmp) // abc
}
const
包含let
的所有特性,但const
声明的变量是常量
。不能重复赋值。let
是可以的.
const aa = 111;
console.log(aa) // 111
aa = 222; // 报错 TypeError: Assignment to constant variable.
console.log(aa) // 111
var
存在变量提升var
来讲,在function
中才有作用域。如果不在function
中那么就是全局作用域var
可以重复声明同一变量var
可以给变量重复赋值var
可以在变量未声明之前去使用变量(变量提升导致的)理解了上面var、let、const
的相关特性后,再来看题主的问题:
for (var i =0; i < 3; i++) {
var i = 3;
console.log(i)
}
解析
i
是通过var
声明的。所以i
会存在变量提升,i
将会提升到全局作用域中。var i = 3
。那么var
声明的变量作用域只有function
和全局
。所以这一步操作会将全局变量i重新赋值为3.i < 3
吗?不小于。所以循环结束了。for (var i =0; i < 3; i++) {
console.log(i)
}
解析
这个循环和第一个没有区别,只是循环体内少了一步操作:var i = 3
。所以会循环到条件终止。
for (var i =0; i < 3; i++) {
let i = 3;
console.log(i)
}
解析
let
来讲,代码块是存在作用域的,其会绑定到当前的作用域中。外部变量并不会影响到该作用域中let
声明的变量var
来讲,代码块是不存在作用域的,所以var
声明的变量会到全局中。i
, 所以会循环3
次console.log(i)
输出的是let
声明的变量i
,所以会一直打印3
.打完收功。
推荐题主看下es6相关的内容...
阮一峰的es6书籍:https://es6.ruanyifeng.com/
6 回答3.1k 阅读✓ 已解决
8 回答4.9k 阅读✓ 已解决
6 回答3.7k 阅读✓ 已解决
5 回答3k 阅读✓ 已解决
6 回答2.5k 阅读
5 回答6.5k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
因为变量提升的缘故,你的第一段代码实际上等效于
第一次循环后, i 被赋值成了 3 ,所以第二次的时候,
i < 3
不成立了,就不会执行了。如果你想要达到预期,就应该使用函数创建一个新的作用域,这样就可以了。