详解var、let、const关键词声明变量的区别,以及变量提升、块级作用域的认识等。
首先回顧一下JavaScript中var聲明變量的基礎知識:
? 在使用var關鍵詞聲明變量時,變量在函數外則是全局變量,有全局作用域,全局變量在頁面關閉后銷毀;變量在函數內則是局部變量,作用局部作用域(變量只能在該函數內有效,函數執行完將自動銷毀)
? 我們使用var來創建變量,聲明后未賦值的變量輸出會提示 “undefined”。在方法函數外聲明的變量未使用var ,會報錯“x is not defined”;
? 在函數內未使用var聲明的變量自動變為全局變量
開發背景(WHY)為什么要使用let、const關鍵詞來創建變量或常量
?解決ES5使用var初始化變量時會出現的變量提升問題
?解決使用閉包時出錯的問題
?解決使用計數的for循環變量時候會導致泄露為全局變量的問題,
?ES5只有全局作用域和函數作用域(對應var聲明的全局變量和局部變量時),沒有塊級作用域(ES6中{}中的代碼塊)。同理只能在頂層作用域window中和函數中聲明函數,不能在塊級作用域中聲明函數;
那么先來理解一下什么是變量提升特性,會導致的問題(比如內層變量覆蓋外層變量)
?變量初始化時可以分為兩步:使用關鍵詞var聲明變量,以及賦值。變量提升就是將聲明變量這一步提升到該作用域的頭部。注意函數聲明也會類似var聲明出現提升特效,函數聲明提升在變量聲明提升上面;
參考網址:https://blog.csdn.net/recoluan/article/details/79253223
實例01
console.log(foo); console.log(foo2); var foo=2; let foo2=3;
//以上代碼var聲明變量后,相當于如下 // var foo; // console.log(foo); //會提示‘undefined’ // foo=2; // let不存在變量提升,會報錯
實例02
var a="我在外面"; function func(){ console.log(a); //undefined console.log(window.a); //我在外面 var a='我在里面'; console.log(a); //我在里面} //以上代碼var聲明變量后,相當于如下 // var a="我在外面"; // function func(){ // var a; // console.log(a); // console.log(window.a); // a='我在里面'; // console.log(a); // }
注意:在使用let、const命令聲明的變量不具備變量提升效果;
????:函數聲明提升會在變量聲明提升上面
fuc2(); function fuc2(){ console.log(b); //undefined} var b=35; //相當于 // function fuc2(){ // console.log(b); // } // var b; // func2(); // b=35;
為什么需要塊級作用域?
??用來計數的循環變量泄露為全局變量,如下:
for (var i = 0; i < s.length; i++) { console.log(s[i]); //會將字符串拆分為一個個的字符輸出}console.log(i); // 5? let和const是ES6新增特性,都可生成塊級作用域(是指聲明在花括號內的變量只在該區域內有效)。let用來聲明變量,const用來聲明常量(不可修改變量值,數組和對象除外);如果區塊內存在let或const命令,這個區塊對這些命令聲明的變量會形成封閉的區域,該區域外不能被使用,且變量聲明前使用變量會報錯(又叫暫時性死區),更加嚴謹
var tmp = 123;if (true) { tmp = 'abc'; // ReferenceError,不能未聲明前使用這就是暫時性死區 console.log(temp); let tmp; temp=666; console.log(temp);}塊級作用域外不能訪問該區塊內的變量或者常量,子塊級作用域可以訪問父塊級作用域的變量
{ const ss=99;{ console.log(ss); //可以在子塊內訪問父塊定義的常量}}console.log(ss); //b不可以在塊作用外訪問let、const定義的變量或者常量以上代碼中通過將let替換var就可以修復各種bug,所以,“let是更完美的var”。
其他的let、const和var的用法及注意點
? let和var的區別:let聲明的變量只在其聲明的塊或子塊中可用,而var聲明的變量的作用域是整個封閉函數可用;
? let和const的特點:
① let和const關鍵詞聲明的變量不具備變量提升的特效(第二步提到了的),存在暫時性的死區,只能在聲明的位置后使用,同一塊級作用域中不能反復聲明同一變量名(子塊級可以重復聲明父塊級變量),var可以;
② let和const聲明只在最靠近的一個塊(花括號內)中有效;
③ 使用const聲明常量時候大寫,const在聲明時必須賦值;
注意1: const聲明的變量值并不是不能變的,而是變量指向的內存地址是不能變的,對于數值、字符串等簡單類型的數據,值就保存在變量指向的內存地址上,因此等同于常量;但對于符合類型的數據(如數組和對象),變量指向的內存地址是一個指引,數據結構是否可變就不能控制了,所以將對象聲明為常量必須非常小心;
const newArr=[23,43,22,66];newArr[0]=888;console.log(newArr); //[888, 43, 22, 66]注意2:外層塊作用域不可以訪問塊內層作用域,內層塊作用域可以獲取外層塊作用域變量,子塊可以重復定義外層塊作用域變量。函數在塊級作用域中聲明是行為類似let,不能被作用域外訪問,塊中的函數聲明存在變量提升,確實需要時候使用函數表達式的形式,而不是函數聲明語句形式;
function f() { console.log('I am outside!'); }(function () { if (false) { //函數提升后,這里重復聲明了該匿名函數外的函數f,所以會覆蓋外部函數 function f() { console.log('I am inside!'); }} f();}());
注意3: ?Let不允許在相同作用域中使用與其他let或const,重復聲明同一個變量,所以不能在有參函數聲明中重復聲明函數參數,如function func(arg){let arg}會報錯
var message = "Hello!";let age = 25;// 以下兩行都會報錯const message = "Goodbye!";const age = 30;注意4: 在ES5中頂層對象(在瀏覽器指的是window對象),頂層對象屬性和全局變量是等價的。屬性也可以動態創建變量,頂層對象的屬性可以被隨處讀寫不利于模塊化編程;而在ES6中,var命令和function命令聲明的全局變量,依舊是頂層對象的屬性;另一方面規定,let命令、const命令、class命令聲明的全局變量,不屬于頂層對象的屬性。也就是說,從 ES6 開始,全局變量將逐步與頂層對象的屬性脫鉤。
var aaa=1;console.log(window.aaa); //輸出1let bbb=2;console.log(window.bbb ); //輸出undefined總結
以上是生活随笔為你收集整理的详解var、let、const关键词声明变量的区别,以及变量提升、块级作用域的认识等。的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: js数组遍历和对象遍历
- 下一篇: rust(51)-rust工具,prel