ES3 定義變量 和 ES6 定義變量的區別

varlet 的區別,實際上就是 ES3 定義變量 和 ES6 定義變量的區別javascript

  • ES3 定義變量的方式:
    • var
    • function
  • ES6 定義變量的方式:
    • let
    • const
    • class
    • import

ES6 語法相對於 ES3 來講,最大的特色就是讓 JS 變得更加嚴謹,告別 JS 鬆散的特色java

思惟導圖

1、LETVAR 的區別

一、變量提高方面

  • let 不存在變量提高,因此變量只能在聲明定義後使用
  • var 存在變量提高
console.log(n); //=>undefined
var n = 10;
console.log(n); //=>10

console.log(n); //=>Uncaught ReferenceError: Cannot access 'n' before initialization LET不存在變量提高,因此變量只能在聲明定義後使用
let n = 10;
console.log(n); //=>10 
複製代碼

二、重複聲明方面

  • let 是不容許重複聲明的
    • 在當前上下文中,無論用什麼方式,只要聲明瞭這個變量,都不能基於 let 重複聲明瞭,會報錯
    • 是否從新聲明,並非在代碼執行階段檢測的,而是在詞法解析的階段檢測的
  • var 容許重複聲明
    • 瀏覽器自己只識別一次,但不會報錯
var n = 12;
var n = 13;
console.log(n); //=>13

let n = 12;
let n = 13;
console.log(n); //=>Uncaught SyntaxError: Identifier 'n' has already been declared

var n = 12;
let n = 13; //=>Uncaught SyntaxError: Identifier 'n' has already been declared

//=>是否從新聲明,並非在代碼執行階段檢測的,而是在詞法解析階段檢測的(詞法解析階段相似於變量提高,在代碼尚未執行以前,就發生了,一旦發現有詞法錯誤 SyntaxError ,當前代碼都不會再執行了)
console.log('OK');
var n = 12;
let n = 13; //=>報錯 可是OK都沒有被執行
複製代碼

詞法解析、詞法錯誤、語法錯誤

  • 詞法解析:詞法解析階段相似於變量提高,在代碼尚未執行以前就發生了
  • 詞法錯誤SyntaxError :在詞法解析階段報錯,代碼尚未執行就報錯,一旦發現有詞法錯誤 SyntaxError ,當前代碼不會在執行了
  • 語法錯誤ReferenceError:在代碼執行階段報錯,報錯前的代碼會正常執行

三、全局對象GO方面

在全局上下文中面試

  • let 聲明的變量僅僅是全局變量,和GO沒什麼關係
  • var 聲明的變量便是全局變量,也至關於給GO(window)設置了一個屬性,並且二者創建映射機制
var n = 10;
console.log(window.n); //=>10

let n = 10;
console.log(window.n); //=>undefined
複製代碼

四、暫時性死區問題

  • let能解決基於typeof檢測一個沒有被聲明過的變量結果是"undefined"的暫時性死區問題;
  • var 不能

瀏覽器有一個BUG(暫時性死區):基於typeof檢測一個沒有被聲明過的變量,並不會報錯,結果是"undefined";可是從正確角度來說應該報錯纔是正常的!瀏覽器

console.log(typeof n); //=>"undefined"

//=> 若是這個變量在後面會用`LET`聲明,則前面再基於`typeof`檢測就會報錯:不能在聲明以前使用
console.log(typeof n); //=>Uncaught ReferenceError: Cannot access 'n' before initialization
let n = 10;
複製代碼

五、塊級做用域

  • let 在遇到除對象/函數等大括號之外的大括號(例如判斷和循環)時,會造成新的塊級做用域
  • var 沒有塊級做用域

2、LET 的塊級做用域

在整個JS中,目前爲止咱們接觸的上下文(做用域)只有兩種閉包

  • 全局上下文 EC(G)
  • 函數執行造成的私有上下文 EC(XX)

此時循環體或者判斷體等,都不會單獨造成私有的上下文,裏面的變量都是所在上下文中的變量。函數

if (1 === 1) {
    var n = 10;
    console.log(n); //=>10
}
console.log(n); //=>10

for (var i = 0; i < 5; i++) {...}
console.log(i); //=>5
複製代碼

可是在ES6中,提供了一個新的上下文(做用域)形式:塊級做用域ui

  • 除對象/函數等大括號之外,若是在其他的大括號中(例如:判斷和循環)出現 LET/CONST 等,則會把當前大括號包起來的部分造成一個獨立的私有上下文,基於 LET/CONST建立的變量是當前塊級做用域域中的私有變量;
if (1 === 1) {
    var n = 10; //=>n是全局變量
    let m = 20; //=>m是當前大括號包起來的 私有的 塊級做用域中的 私有變量
    console.log(m); //=>20
}
console.log(n); //=>10
console.log(m); //=>Uncaught ReferenceError: m is not defined


// 相似於造成兩個閉包(這裏叫作私有的塊級做用域)
{
    let x = 10,
        y = 20;
    console.log(x, y);
}
{
    let x = 100,
        y = 200;
    console.log(x, y);
}


for (let i = 0; i < 3; i++) {
    console.log(i); //=>0 1 2
}
console.log(i); //=>Uncaught ReferenceError: i is not defined
複製代碼

循環中遇到let/const

  • 圖解:
  • 一、建立一個總的塊級做用域(父做用域):用來控制循環一輪輪執行
  • 二、每一輪循環都會造成一個新的私有上下文(子做用域):
    • 用來實現循環中要處理的業務需求
    • 會把每一輪循環 i 的值,做爲子做用域中的私有變量

和咱們基於 VAR ,每一輪循環都建立一個閉包相似spa

3、LETCONST 的區別

  • CONST聲明的變量,不能從新指向新的值(不能修改指針的指向);
let n = 10;
n = 20;
console.log(n); //=>20

const n = 10;
n = 20; //=>Uncaught TypeError: Assignment to constant variable.
console.log(n);
複製代碼

一道經典面試題

const 定義的變量值,永遠不能被修改了?指針

  • 答:不對
  • 一、const 不能更改指的是:這個變量不能在和其餘值進行關聯了,也就是不能修改 const 聲明變量的指向
  • 二、可是能夠在不改變指向的狀況下,修改堆內存中的信息(這樣也是把值更改了)
  • 三、因此:const 聲明的變量,不能修改他的指針指向,可是能夠改變其儲存值的

例以下面這種狀況:code

const obj = {
    name: '金色小芝麻'
};
obj = [10, 20]; //=>Uncaught TypeError: Assignment to constant variable. 
//=> 它不能更改指的是:obj這個變量不能在和其它值進行關聯了,也就是不能修改const聲明變量的指向

obj.name = '哈哈';
console.log(obj);//=>{name: '哈哈'};
 //=>可是能夠在不改變指向的狀況下,修改堆內存中的信息(這樣也是把值更改了),
 //=> 因此記住:const聲明的變量,不能修改它的指針指向,可是能夠改變其存儲值的
 //=> 因此也就不能說const建立的是一個常量;
複製代碼
相關文章
相關標籤/搜索