一、區(qū)別
1. var
①沒有塊的概念棠赛,可以跨塊訪問哮奇,但不能跨函數(shù)訪問;
②作用域在該語句所在的函數(shù)內(nèi)睛约,且存在變量提升現(xiàn)象鼎俘;
(啥?你問我啥是塊辩涝?像for贸伐、if等這些創(chuàng)建的{}
,都屬于塊作用域)
function bar(){
{
var a = 1
}
console.log(a)
}
bar() // 1
function bar(){
{
let a = 1
}
console.log(a)
}
bar() // ReferenceError: a is not defined
for(i = 1; i < 5; i++){
console.log(i);//1 2 3 4
}
console.log(i);//5
for(let j = 1; j < 5; j++){
console.log(j);//1 2 3 4
}
console.log(j);//ReferenceError: j is not defined 因?yàn)閖只在for那個(gè)塊里定義了
2. let
①只能在塊作用域里訪問怔揩,不可以跨塊訪問捉邢,更不能跨函數(shù)訪問脯丝;
②作用域在該語句所在的代碼塊中,且不存在變量提升現(xiàn)象伏伐;
③let在相同的作用域下宠进,不允許重復(fù)聲明變量;
④存在暫時(shí)性死區(qū)藐翎,在變量聲明之前是不能使用的砰苍,否則會(huì)報(bào)錯(cuò);
3. const
①const用來定義常量阱高,使用時(shí)必須初始化(即必須賦值赚导,不賦值就會(huì)報(bào)錯(cuò));
②和let一樣只能在塊作用域里訪問赤惊,而且不能修改吼旧;
③const聲明的常量也是不提升,同樣存在暫時(shí)性死區(qū)未舟,只能在聲明的位置后面使用圈暗,而且也是不能重復(fù)聲明;
但是T0颉T贝!
image.png
二昼扛、for循環(huán)與let寸齐、var
1、第一種
- 結(jié)果:1s后打印出6個(gè)6抄谐;
- 詳解:
①首先它會(huì)先執(zhí)行同步代碼即6個(gè)循環(huán)代碼渺鹦,同步代碼執(zhí)行完畢后,再執(zhí)行異步代碼即setTimeout里的函數(shù)蛹含;
②因?yàn)閘et是聲明在循環(huán)外的毅厚,每次同步的循環(huán)代碼執(zhí)行時(shí),i是在同一個(gè)作用域下浦箱,所以每次循環(huán)的時(shí)候變化的是同一個(gè)i吸耿;
③當(dāng)開始執(zhí)行異步代碼時(shí),這時(shí)的i已經(jīng)是6了酷窥,所以執(zhí)行6個(gè)異步的console.log(i)咽安,就會(huì)打印出6個(gè)6了;
function f1(){
let i
for(i=0; i<6; i++){
setTimeout(()=>{console.log(i)}, 1000)
}
}
f1()
2竖幔、第二種
- 結(jié)果:1s后打印出012345板乙;
- 詳解:
①它與上面的不同點(diǎn)就是在于let聲明的位置是偷,這里let是在每次循環(huán)的時(shí)候都去聲明一個(gè)i拳氢,所以每次循環(huán)的i都不是同一個(gè)募逞,這樣最后就會(huì)打印出當(dāng)時(shí)循環(huán)體聲明的i,即012345
function f2(){
for(let i=0; i<6; i++){
setTimeout(()=>{console.log(i)}, 1000)
}
}
f2()
3馋评、第三種
- 結(jié)果:1s后打印出012345放接;它跟第二種結(jié)果是一樣的,只是實(shí)現(xiàn)方式不同留特;
- 詳解:
①用var來聲明纠脾,但是var會(huì)提升至函數(shù)頭部;
②把setTimeout放到一個(gè)立即執(zhí)行函數(shù)中去蜕青,并把每一次循環(huán)的i傳進(jìn)去苟蹈,這樣每一個(gè)setTimeout接受到的就是不同的i了;
function f3(){
for(var i=0; i<6; i++){
!function(i){
setTimeout(()=>{console.log(i)}, 1000)
}(i)
}
}
f3()