1.塊級作用域
什么是:
在一個代碼塊(括在一對花括號中的一組陳述句)中定義的所需變數(與let配合使用)并在代碼塊的外部是不可見的,
為什么:
在ES6之前,函式只能在全域作用域和函式作用域中宣告,不能在塊級作用域中宣告,造成諸多問題:
1.內層變數會覆寫外層變數
2.用來計數的回圈變數泄漏變成全域變數
何時:
需要強化對變數生命周期的控制,避免全域污染出現錯誤
優點:
1.阻止變數泄漏變為全域變數,造成全域污染
2.阻止變數提升覆寫
3.內層作用域可以定義與外層作用域相同的變數名,但變數是獨立的,
4.允許任意嵌套,外層作用域無法讀取內層作用域的變數
塊級作用域:
{},if{},else{},while{},for{},swicth{}…
//塊級作用域{},與let配合使用 { //大括號之間就是塊級作用域 var num=1;//還是全域變數,可以被外部訪問 let num=1;//區域變數,不可以被外部訪問,塊級作用域必須用let宣告 } console.log(num);//此時num已經不可以被訪問,說明塊級作用域生效 //內層作用域可以定義與外層作用域相同的變數名,允許任意嵌套 //但變數與變數之間是沒有關系的,都是獨立的個體, { let aa=1; console.log(aa);//1 { let aa=11; console.log(aa);//11 { let aa=111; console.log(aa);//111 } } } console.log(aa);//此時是不能被訪問的,防止aa泄露為全域變數 //防止變數提升造成覆寫 //雖然都是f,但是配合了let使用,{}內部變成了一個小個體,不會影響其他的f var f=17; { let f=28; console.log(f); } console.log(f); //for塊級作用域 //計算1-100之間所有的整數的和,使用var宣告 for (var i=1,sum=0;i<=100;i++){ sum+=i; } console.log(sum);//5050,可以訪問 console.log(i);//101,可以訪問 //使用let宣告變數 for (let i=1,sum=0;i<=100;i++){ sum+=i; } console.log(i);//此時i是不能被訪問的, console.log(sum);//此時sum是不能被訪問的, //根據需求得知,最后需要訪問的是sum,i需要釋放 //所以把sum單獨放在外面,sum就可以被訪問,而i會被釋放 var sum=0; for (let i=1;i<=100;i++){ sum+=i; } console.log(sum);
2.let宣告
什么是:
專門代替var來宣告變數用的
為什么:
var的問題:
1.宣告提前
2.沒有塊級作用域
3.造成全域污染
何時:
只要宣告變數都用let
優點:
1.阻止了宣告提前
2.添加了塊級作用域
3.成為區域變數,不會造成全域污染
原理:
let其實就是一個匿名函式自呼叫!
且let為了雙保險,其實在底層悄悄給變數改了名字,在變數前增加了_
let的小脾氣:
1.在相同作用域/塊內:禁止同時let兩個同名的變數
2.在let 變數 之前到當前作用域的頂部之間,不允許提前使用變數
3.不可以在函式內部重復宣告引數
//1.簡單了解let宣告的變數 let a=2; console.log(a); let a=3; console.log(a);//報錯,a不能重復宣告并賦值 //var宣告的變數可以重復宣告并重新賦值 var b=2; console.log(b);//2 var b=3; console.log(b);//3 //在塊級作用域內{} { var c=2; let c=4;//在同一塊級作用域內不允許重復宣告變數 let d=3; console.log(d);//只能在當前{}塊級作用域內訪問 } console.log(c);//可以被外部訪問的是var宣告的c console.log(d);//不可以被外部訪問 //let不允許先呼叫,后宣告 { console.log(aaa); let aaa=5;//報錯Cannot access 'aaa' before initialization }
把let放入實體中理解
//let應用 //累加每個任務函式的時間 var t=0; function task1(){ console.log(`任務1耗時3s`); t+=0.3; } function task2(){ console.log(`任務二耗時8s`); t+=0.8; } task1(); task2(); console.log(`共耗時${t}s`)以上是一個可以正常執行的代碼,并且是正確的程式 如果在task2內添加其他的功能,例如捕捉錯誤
//累加每個任務函式的時間 var t=0;//宣告變數t準備累加每個任務函式的時間 function task1(){ console.log(`任務1耗時3s`); t+=3; } function task2(){ console.log(`任務二耗時8s`); t+=8; //模擬出錯的變數,此段代碼是不執行的 var err=false; //如果出錯 if(err==true){ //就獲得出錯時間 var t=new Date(); //并輸出出錯提示日志 console.log(`出錯啦,at:${t.toLocaleDateString()}`); }; } task1(); task2(); console.log(`共耗時${t}s`)代碼正常執行,if內代碼是不執行的,但是結果卻是錯誤的,少了8s,那么為什么少了8s呢? 原來是因為var宣告的變數是全域變數,而if{}不是作用域,沒有物體墻,攔不住var, 所以var宣告的變數會提升到當前作用域task2的最前面,
//累加每個任務函式的時間 var t=0;//全域t function task1(){ console.log(`任務1耗時3s`); t+=3; } function task2(){ //var t;//undefined,var宣告的t提前到該作用域最前面,并且沒有賦值 //如果task2()中已經有了區域變數t,就不會用全域的t了,只有在區域沒有的t的時候才會呼叫全域的t console.log(`任務二耗時8s`); //這個8s沒有加到全域t,而是加在區域t上,當函式呼叫后,區域的t就被釋放了 t+=8;//task2中的區域變數t,加在這里 var err=false;//模擬出錯的變數 //如果出錯 if(err==true){//if else for while do whlie 等程式結構的{}不是作用域,不是物體墻,攔不住var //就獲得出錯時間 var t=new Date(); //并輸出出錯提示日志 console.log(`出錯啦,at:${t.toLocaleDateString()}`); }; } task1(); task2(); console.log(`共耗時${t}s`)//此處輸出的是全域的t,所以沒有那8s,那么鑒于這種明明沒有執行的代碼,卻破壞了原本正確的代碼, 這就是沒有塊級作用域帶來的危害,此時就需要使用let宣告變數了, 因為let會阻止宣告提前,并會添加塊級作用域
//累加每個任務函式的時間 var t=0;//全域t function task1(){ console.log(`任務1耗時3s`); t+=3; } function task2(){ console.log(`任務二耗時8s`); t+=8;//這個t還是會加到全域的t上,沒有被影響 //模擬出錯的變數 //var err=false;//代碼不執行 var err=true;//代碼執行 //如果出錯 if(err==true){//let將if{}也變成了一級作用域,這個作用域是有物體墻的,是可以攔住let宣告的變數的 //就獲得出錯時間 //let阻止了區域的t被宣告提前 let t=new Date();//此時的t是在這個if塊級作用域的函式內,不會存在提升 //并輸出出錯提示日志 console.log(`出錯啦,at:${t.toLocaleDateString()}`);//所以此時輸出的t也是if內的t }; } task1(); task2(); console.log(`共耗時${t}s`)//列印全域tlet的原理,添加匿名函式自呼叫,并改變名字
//累加每個任務函式的時間 var t=0;//全域t function task1(){ console.log(`任務1耗時3s`); t+=3; } function task2(){ console.log(`任務二耗時8s`); t+=8;//這個t還是會加到全域的t上,沒有被影響 //var err=false; var err=true;//模擬出錯的變數 //如果出錯 if(err==true){//let將if{}也變成了一級作用域,這個作用域是有物體墻的,是可以攔住let宣告的變數的 //(function(){//let自動添加的 //就獲得出錯時間 //let阻止了區域的t被宣告提前 let t=new Date();//let悄悄改變了名字,變成了_t,此時的t是在這個if塊級作用域的函式內,不會存在提升到 //并輸出出錯提示日志 console.log(`出錯啦,at:${t.toLocaleDateString()}`);//_t,所以此時輸出的t也是if內的t //})();//let自動加的 }; } task1(); task2(); console.log(`共耗時${t}s`)//列印全域t
單詞:
declare——宣告
access——訪問
initialization——初始化——>第一次宣告+賦值=初始化
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/146320.html
標籤:JavaScript
