2020-Es6(let 和 const)

1.let 和 const

let
1.不存在變量提升(什麼是變量提升)

 console.log(carName)
 // 在這裏可以使用 carName 變量,不報錯
var carName;         
console.log(carName)
// 在這裏不可以使用 carName 變量,報錯
let carName;

2.同一個作用域下不能重複定義同一個名稱

  var a=0;
  var a=1; //不報錯,a爲1
  let a= 0;
  let a=1 //報錯

3.有塊級作用域,var只有函數作用域

{
  let a = 10;
  var b = 1;
}

a // 報錯,所在作用域未聲明a
b // 1

4.暫時性死區

只要塊級作用域內存在let命令,它所聲明的變量就“綁定”(binding)這個區域,不再受外部的影響。

var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;  //只要代碼塊let了一個變量,
            //那這個變量就不能在被let之前使用
}

有些“死區”比較隱蔽,不太容易發現。

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

bar(); // 報錯

個人猜測相當於

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

bar(); // 報錯

5.爲什麼需要塊級作用域
第一種場景,內層變量可能會覆蓋外層變量。

var tmp = new Date();

function f() {
  console.log(tmp);
  if (false) {
    var tmp = 'hello world';
  }
}

f(); // undefined

第二種場景,用來計數的循環變量泄露爲全局變量。

var s = 'hello';

for (var i = 0; i < s.length; i++) {
  console.log(s[i]);
}

console.log(i); // 5

使用let的話, i 便是塊級作用域的變量,外層作用域無法使用

ES6 的塊級作用域必須有大括號,如果沒有大括號,JavaScript 引擎就認爲不存在塊級作用域。

// 第一種寫法,報錯
if (true) let x = 1;

// 第二種寫法,不報錯
if (true) {
  let x = 1;
}

const
let的特性const基本都有,不同的是
const聲明一個只讀的常量。一旦聲明,常量的值就不能改變。

const PI = 3.1415;
PI // 3.1415

PI = 3;//報錯

const實際上保證的,並不是變量的值不得改動,而是變量指向的那個內存地址不得改動。

const foo = {};

// 爲 foo 添加一個屬性,可以成功
foo.prop = 123;
foo.prop // 123

// 將 foo 指向另一個對象,就會報錯
foo = {}; // TypeError: "foo" is read-only

如果真的想將對象凍結,應該使用Object.freeze方法。

const foo = Object.freeze({});
// 常規模式時,下面一行不起作用;
// 嚴格模式時,該行會報錯
foo.prop = 123;

除了將對象本身凍結,對象的屬性也應該凍結。下面是一個將對象徹底凍結的函數。

var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach( (key, i) => {
    if ( typeof obj[key] === 'object' ) {
      constantize( obj[key] );
    }
  });
};

var命令和function命令聲明的全局變量,依舊是頂層對象(window)的屬性;另一方面規定,let命令、const命令、class命令聲明的全局變量,不屬於頂層對象的屬性。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章