1. 程式人生 > >ES6Script - let & const命令

ES6Script - let & const命令

let -用法類似var,用來宣告變數,但是所宣告的變數,只在let命令所在的程式碼塊內有效。
test:

{
 let a=10;
 var b=1;

}
b  //10
a //a is not defined

使用var宣告
i是var宣告的,在全域性範圍內都有效,結果是10

var  a=[];
for(var i=0;i<10;i++){
a[i]=function(){
	console.log(i);
}
}
a[6]();

使用let 宣告,塊級作用域有效,結果是6
變數i是let宣告的,當前的i只在本輪迴圈有效,所以每一次迴圈的i其實都是一個新的變數,所以最後輸出的是6

var  a=[];
for(let i=0;i<10;i++){
a[i]=function(){
	console.log(i);
}
}
a[6]();

for迴圈還有一個特別之處,就是設定迴圈變數的那部分是一個父作用域,而迴圈體內部是一個單獨的子作用域。
不存在變數提升

console.log(a);
let a=1;// uundefined
暫時性死區
只要塊級作用域記憶體在let命令,它所宣告的變數就“繫結”(binding)這個區域,不再受外部的影響

var t=1;
if(true){
t='1';
let t;
}

存在全域性變數t,但是塊級作用域內let又聲明瞭一個區域性變數t,導致後者繫結這個塊級作用域,所以在let宣告變數前,對t賦值會報錯
有些“死區”比較隱蔽,不太容易發現。

function bar(x = y, y = 2) {
  return [x, y];
}

bar(); // 報錯
上面程式碼中,呼叫bar函式之所以報錯(某些實現可能不報錯),是因為引數x預設值等於另一個引數y,而此時y還沒有宣告,屬於”死區“。如果y的預設值是x,就不會報錯,因為此時x已經聲明瞭。
不允許重複宣告
let不允許在相同作用域內,重複宣告同一個變數

// 報錯
function func() {
  let a = 10;
  var a = 1;
}

// 報錯
function func() {
  let a = 10;
  let a = 1;
}

塊級作用域


let實際上為JavaScript新增了塊級作用域

function f1(){
let n=5;
if(true){
let n=10;
}
console.log(n);
}

上面的函式有兩個程式碼塊,都聲明瞭變數n,執行後輸出 5。這表示外層程式碼塊不受內層程式碼塊的影響。如果兩次都使用var定義變數n,最後輸出的值才是 10。

ES6 允許塊級作用域的任意巢狀 外層作用域無法讀取內層作用域的變數。
{{{{let insane=‘hello’}}}};
塊級作用域與函式宣告
函式只能在頂層作用域和函式作用域之中宣告

// 情況一
if (true) {
  function f() {}
}

// 情況二
try {
  function f() {}
} catch(e) {
  // ...
}

上面語句 根據 ES5 的規定都是非法的。

但是,瀏覽器沒有遵守這個規定,為了相容以前的舊程式碼,還是支援在塊級作用域之中宣告函式,因此上面兩種情況實際都能執行,不會報錯。
ES6 引入了塊級作用域,明確允許在塊級作用域之中宣告函式。ES6 規定,塊級作用域之中,函式宣告語句的行為類似於let,在塊級作用域之外不可引用。

function f() { console.log('I am outside!'); }

(function () {
  if (false) {
    // 重複宣告一次函式f
    function f() { console.log('I am inside!'); }
  }

  f();
}());

const 命令
const宣告一個只讀的常量。一旦宣告,常量的值就不能改變。

const PI = 3.1415;
PI // 3.1415

PI = 3;

const實際上保證的,並不是變數的值不得改動,而是變數指向的那個記憶體地址所儲存的資料不得改動。對於簡單型別的資料(數值、字串、布林值),值就儲存在變數指向的那個記憶體地址,因此等同於常量。但對於複合型別的資料(主要是物件和陣列),變數指向的記憶體地址,儲存的只是一個指向實際資料的指標,const只能保證這個指標是固定的(即總是指向另一個固定的地址),至於它指向的資料結構是不是可變的,就完全不能控制了。因此,將一個物件宣告為常量必須非常小心。
物件凍結,應該使用Object.freeze方法
頂層物件的屬性
頂層物件,在瀏覽器環境指的是window物件,在 Node 指的是global物件。ES5 之中,頂層物件的屬性與全域性變數是等價的。
,var命令和function命令宣告的全域性變數,依舊是頂層物件的屬性;另一方面規定,let命令、const命令、class命令宣告的全域性變數,不屬於頂層物件的屬性。也就是說,從 ES6 開始,全域性變數將逐步與頂層物件的屬性脫鉤。

var a = 1;
// 如果在 Node 的 REPL 環境,可以寫成 global.a
// 或者採用通用方法,寫成 this.a
window.a // 1

let b = 1;
window.b // undefined

上面程式碼中,全域性變數a由var命令宣告,所以它是頂層物件的屬性;全域性變數b由let命令宣告,所以它不是頂層物件的屬性,返回undefined。