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.不能夠在函數內部重複聲明參數spa
//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`)
//累加每一個任務函數的時間 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`)
//累加每一個任務函數的時間 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,
//累加每一個任務函數的時間 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`)//打印全局t
//累加每一個任務函數的時間 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——初始化——>第一次聲明+賦值=初始化code