ES6中的變量聲明


一、為什么要是用let和const代替var聲明變量

  1、var聲明的變量是函數作用域的,存在變量的提升。(變量的聲明會被提前到當前作用域的最前面)

 1 //變量提升
 2 function f(condition){  3     if(condition){  4         var value="blue";  5         return value;  6  }  7     else{  8         console.log(value); //undefined
 9  } 10     console.log(value);  //undefined
11 } 12 f(false);

    由於var聲明的變量存在變量提升,所以當condition為false時,輸出變量不會提示value變量未定義的錯誤,上面的代碼類似於

 1 //變量提升
 2 function f(condition){  3     var value;  4     if(condition){  5         value="blue";  6         return value;  7  }  8     else{  9         console.log(value); //undefined
10  } 11     console.log(value);  //undefined
12 } 13 f(false);

  2、var可以在同一作用域內聲明一個變量多次。變量的值為最后一次聲明的 

1 var value=10; 2 var value="100"; 3 console.log(value)//100

   3、全局作用域的綁定

  使用var聲明的全局變量會自動綁定為全局對象的屬性。從而又可能覆蓋已經存在的全局屬性。

1 console.log(global.RegExp);//[Function: RegExp]
2 var RegExp="aaa"; 3 console.log(global.RegExp);//"aaa"

  代碼不要寫在js文件中使用node 文件名去測試,因為node會把一個文件作為一個模塊,聲明的變量不是全局對象的屬性。

  可以node的repl中測試或者瀏覽器環境中。

  使用let和const聲明的變量不會覆蓋全局對象的屬性,而是遮蓋他  

1 let RegExp="aaa"; 2 console.log(global.RegExp===RegExp);//false  

二、let和const

  通過let和const聲明的變量是塊級作用域,只在{}生效;類C語言多采用塊級作用域,這樣做更符合我們的習慣。

  let聲明

  a、let聲明的變量是塊級作用域,且不存在變量提升機制,所以使用let聲明的 變量只有放到當前作用域的最前面,才能在整個作用域中使用。

 1 function f(condition){  2     if(condition){  3         let value="blue";  4         return value;  5  }  6     else{  7         //console.log(value); //ReferenceError: value is not defined
 8  }  9     console.log(value);  //ReferenceError: value is not defined
10 } 11 f(true);

  變量離開if塊就會被銷毀,其他的塊作用由於沒有什么變量vaue,所以直接使用會拋出異常。

  b、let聲明的變量在同一作用域中禁止重復聲明

1 //var value=10;
2 let value=10; 3 let value="100";//SyntaxError: Identifier 'value' has already been declared
4 console.log(value)//100

 當在不同的作用域聲明變量的時候,不會報錯。

1 //var value=10;
2 let value=10; 3 function f(){ 4     let value="1dad"; 5     console.log(value)//'1dad'
6 } 7 console.log(value)//10
8 f()

  const聲明

  a.const關鍵字用來聲明一個常量,聲明后變量的值不可以更改。const聲明變量必須初始化。

1 const a='dada'
2 const b;//SyntaxError: Missing initializer in const declaration

  b、const聲明已存在的變量會報錯,(無論是let和const) 

var a=10; //let a=10
const a='dada'//Identifier 'a' has already been declared

  c、用const聲明對象

  const聲明的變量不允許修改變量的值。由於變量存在的是對象的值得引用,所以const聲明的對象可以修改對象的屬性,但是不能把修改對象的引用。

const  a={name:'yiluhuakai'}; a.name="aaa"; console.log(a.name)//'aaa'
a={};//TypeError: Assignment to constant variable.

三、臨時死區

  使用let和const聲明的變量不會進行變量提升,變量的作用域的開始到變量聲明之前的位置成為臨時死區,當在該區域使用變量時回拋出異常,即使是使用相對安全的typeof操作符。  

typeof a;//作用域外不會拋出異常
function f(){ // typeof a;//ReferenceError: a is not defined
    if(true) { ; } let a=10; } f();

四、循環中的函數

  在循環中定義一個函數,打印當前的循環的變量i;

 1 var arr=[];  2 for(var i=0;i<10;i++){  3     arr.push(function(){  4  console.log(i);  5  })  6 }  7 //打印
 8 arr.forEach(function(item){  9     item();//輸出10次10
10 })

   為什么輸出結果是10次10呢,因為上面var聲明的便利會提升到循環外面,循環中函數共享(閉包)同一個i。

   立即調用調用函數可以解決這個問題。  

 1 var arr = [];  2 for (var i = 0; i < 10; i++) {  3     arr.push((function (value) {  4         return function () {  5  console.log(value)  6  }  7  })(i))  8 }  9 //打印
10 arr.forEach(function (item) { 11     item();//0 1 2 ... 8 9
12 })

  將i作為行參傳給函數,value會復制i的值,這個之就是內部函數打印的值。

  更簡單的解決辦法:使用let使命變量

 1 var arr=[];  2 for(let i=0;i<10;i++){  3     arr.push(function(){  4  console.log(i);  5  })  6 }  7 //打印
 8 arr.forEach(function(item){  9     item();//輸出0 1 ... 8 9
10 })

  使用let聲明的變量每次循環都會聲明一個新的變量,所以之前迭代的同名變量初始化j將其初始化,所以每次輸出的值都不一樣。

   for-in和for-of也是一樣。

 1 var arr=[];
 2 var object={
 3     a:true,
 4     b:1,
 5     c:2
 6 }
 7 for(let key in object){
 8     arr.push(function(){
 9         console.log(key)
10     })
11 }
12 arr.forEach(function(item){
13     item() //a b c
14 })

  使用let會每次聲明一個新的變量保存key,所以會每次輸出不同的值。使用var使用的是同一個變量,最終輸出都是c.

  const用在循環中 

 1 var arr=[];  2 for(const i=0;i<10;i++){  3     arr.push(function(){  4  console.log(i);  5  })  6 }  7 //打印
 8 arr.forEach(function(item){  9     item();//TypeError: Assignment to constant variable.
10 })

  在普通的for循環中使用const聲明變量時,第一次循環const i=0不會報錯,但是當第二次循環中初始化i后,對i執行i++操作時會報錯。所以不能在普通的循環中使用const聲明循環變量。

  但是在for-of和for-in循環中使用const不會出現問題,因為只會對新創建的變量初始化,不會去改變變量的值。

 1 var arr=[];  2 var object={  3     a:true,  4     b:1,  5     c:2
 6 }  7 for(const key in object){  8     arr.push(function(){  9  console.log(key) 10  }) 11 } 12 arr.forEach(function(item){ 13     item() //a b c
14 }) 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM