var
和 let
的區別,實際上就是 ES3
定義變量 和 ES6
定義變量的區別javascript
ES3
定義變量的方式:
var
function
ES6
定義變量的方式:
let
const
class
import
ES6
語法相對於ES3
來講,最大的特色就是讓JS
變得更加嚴謹,告別JS
鬆散的特色java
LET
和 VAR
的區別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
:在代碼執行階段報錯,報錯前的代碼會正常執行
在全局上下文中面試
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
沒有塊級做用域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
LET
和 CONST
的區別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建立的是一個常量;
複製代碼