前端百題斬【002】——js中6種變量聲明方式

寫該系列文章的初衷是「讓每位前端工程師掌握高頻知識點,爲工做助力」。這是前端百題斬的第2斬,但願朋友們關注公衆號「執鳶者」,用知識武裝本身的頭腦。javascript

隨着js的發展,目前共6種聲明變量的方式,分別爲var、let、const、function、class、import,下面分別闡述一下這六種方式。前端

1 var

在ES5階段,用var定義變量,此階段具備如下特色:
  1. 沒有塊的概念,能夠跨塊訪問,不能跨函數訪問;
  2. 存在變量提高。
// 代碼沒報錯,而是打印出來了undefined,側面說明了val變量存在變量提高
console.log(val); // undefined
var val = 1;
console.log(val); // 1

2 let

在ES6階段,出現了塊的概念,新增了塊級做用域,同時新增了let命令,let聲明的變量具備如下特色:
  1. let聲明的變量只在它所在的代碼塊有效;
  2. 不存在變量提高。let不會像var那樣會發生‘變量提高’現象,所以,變量須要先聲明後再使用,不然會報錯;
  3. 暫時性死區。在代碼塊內,使用let命令聲明變量以前,該變量都是不可用的;
  4. 不容許重複聲明。
// 實驗一——只在所在的代碼塊有效
// 1
{
    let val = 2;
    console.log(val); // 2
}
// 2
{
    let val = 2;
}
console.log(val); // ReferenceError: val is not defined
// 實驗2——不存在變量提高 + 暫時性死區
{
    console.log(val); // 報錯
    let val = 2;
}
// 實驗三——不容許重複聲明
{
    let val = 1;
    let val = 2; // SyntaxError: Identifier 'val' has already been declared
}

3 const

在let命令出現的同時,出現了const命令,其用於聲明一個只讀的常量,具備如下特色:
  1. 一旦聲明就必須當即初始化;
  2. 一旦聲明,常量值就不能改變了(指的是內存地址不能改變);
  3. 塊做用域內有效;
  4. 不存在變量提高;
  5. 存在暫時性死區。
對於上述的驗證代碼能夠用參考let的。
對於const,還有一點比較有意思的指的詳細闡述一下:const實際上保證的並非變量的值不能改動,而是變量指向的那個內存地址不能改動。對於簡單類型的數據而言,值就保存在變量指向的內存地址中,所以等同於常量。但對於複合類型的數據而言,變量指向的內存地址保存的只是一個指針,const只能保證這個指針是固定的,至於指向的數據結構不受控制。那麼如何保證複合類型的值如何保證呢?可使用Object.freeze()方法,該方法使對象的原始屬性不可變,但仍然能夠更改嵌套對象。爲了使對象徹底不可變,經過將嵌套對象上的全部屬性凍結達到效果。
const constantize = obj => {
  Object.freeze(obj);
  Object.keys(obj).forEach( key => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

1.4 function

function命令用於定義一個函數,具備如下特色:
  1. 函數聲明後不會當即執行,須要調用的時候才執行;
  2. 對支持ES5和ES6瀏覽器環境在塊做用域內有必定區別,因此應避免在塊級做用域內聲明函數。
function test() {
    // ……
}

5 class

ES6語法引入了class關鍵字,用來定義類,該寫法相比於對象原型的方式具備如下特色:
  1. 相比於對象原型的方式寫法更清晰;
  2. 更像面向對象編程的語法(對有面向對象編程經驗的同窗更友好)。
class Calculate {
    constructor(x, y) {
        this.x = x;
        this.y = y;
    }
    
    add() {
        return this.x + this.y;
    }
}

6 import

ES6在語言標準的層面上實現了模塊功能,其中import命令就是用於加載模塊,而後輸出變量,其具備如下特色:
  1. import命令接受一對大括號,其裏面的變量名必須與被導入的模塊對外接口的名稱相同;
  2. 用as關鍵字可將輸入的變量名重命名;
  3. import命令輸入的變零都是隻讀的;
  4. import命令具備提高效果,會提高到整個模塊的頭部,首先執行(由於import命令是在編譯階段執行的,在代碼運行以前);
  5. import是靜態執行,不能使用表達式和變量;
  6. import會執行所加載的模塊。
// 隨便舉個例子
import {add} from './calcluate';

7 有意思的小問題

下面四種狀況分別輸出什麼?爲何呢?歡迎各位老鐵留言
  1. 狀況一
for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
  1. 狀況二
for (var i = 0; i < 3; i++) {
  var i = 'abc';
  console.log(i);
}
  1. 狀況三
for (let i = 0; i < 3; i++) {
  var i = 'abc';
  console.log(i);
}
  1. 狀況四
for (var i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}

1.若是以爲這篇文章還不錯,來個分享、點贊吧,讓更多的人也看到java

2.關注公衆號執鳶者,與號主一塊兒斬殺前端百題。編程

相關文章
相關標籤/搜索