1. 程式人生 > >let與const命令

let與const命令

let和var一樣是用來宣告變數的。但是,它與var有很大的不同。

使用let宣告的變數只在其所在的程式碼塊內有效。

if (true) { var a = 1; }

console.log(a); //1

if (true) { let a = 1; }

console.log(a); 報錯

在全域性作用域中,使用let宣告的變數不會是window物件的屬性。

var age = 1;
console.log(window.age) //1
let age = 1;
console.log(window.age) //undefined

let與for迴圈

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

arr[0]() //10
arr[9]() //10

由於變數i指向的是同一個,所以for迴圈結束後,數值變成了10,輸出的也就是10

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

arr[0]() //0
...
arr[9]() //9

當使用了let關鍵字後,每次迴圈都會重新建立i,所以輸出的是0-9

使用let的時候,for的括號內為父作用域,花括號內子作用域,它們之間相互獨立。

for (let i = 0; i < 10; i++) {
  let i = "a";
  console.log(i) //"a"
}

可以看到,兩個變數i之間是獨立的,互相不影響。

for (let i = 0; i < 10; i++) {
  console.log(i) 報錯
  let i = "a";
  console.log(i) //"a"
}

需要注意的是,在作用域內使用一個let宣告的變數的時候,必須是在宣告之後使用,否則一律報錯!
所以可以看到,絕不像var那樣,在變數宣告之前使用變數會輸出undefined,這種現象稱之為變數提升。
而let則杜絕了這種現象,告訴我們先宣告,後使用,才是好習慣!

console.log(a)//undefined
var a = 1;

console.log(a) //報錯
let a = 1;

建立私有作用域

es5:

(function () {

  var a = 1;
  function fn () {}

})()

console.log(a) 報錯
fn() 報錯

es6:

{
  let a = 1;
  let fn = function () {};
}
console.log(a) 報錯
fn() 報錯

不過可惜的是es6的方式不能夠有返回值。

使用const宣告變數

const宣告變數的最大特點是,宣告的時候必須立即初始化,宣告過後不可修改,否則報錯!

const name = 1; //正確

const name; //錯誤

const name = 1; 
name = 2; //錯誤

const與let宣告的變數一樣,只在其所在的程式碼塊內有效,沒有變數提升,必須先宣告,後使用。在全域性作用域中宣告的變數不屬於window物件的屬性。
需要注意的是,對於引用型別的值,const只能保證其記憶體地址不變,因此在物件上進行一些修改是可行的。

const name = {
a : 1
}

name.a = 2;

console.log(name.a) //2

name = {} 錯誤

如果想要凍結物件,可以使用freeze方法。

const obj = Object.freeze({
  name : 1
})

obj.name = 2 //無效 嚴格模式下將報錯

但如果物件中包含有物件型別的值,那麼這個物件內的物件是可變得。

const obj = Object.freeze({
  name : 1,
  arr : [1]
})

obj.arr.push(1)

console.log(obj.arr) //[1,1]

可以使用遞迴方法徹底凍結物件

let frreezeObj = (obj) => {
  //凍結物件
  Object.freeze(obj);
  //object.keys方法返回obj中所有可列舉的屬性的陣列,然後對陣列進行遍歷
  Object.keys(obj).forEach((key, i) => {
    //如果是引用型別的話
    if (typeof obj[key] === 'object') {
      //呼叫自身,將物件凍結
       frreezeObj(obj[key]);
    }
  })
}

let obj = {
  arr : [1]
}

frreezeObj(obj);

obj.arr.push(1) //報錯:物件不可拓展