《es6 標準入門》知識整理(1) - let 和 const

let 基本用法

es6 的 let 所聲明的變量,只在 let 命令所在的代碼塊內有效。for循環的計數器,就很適合用let命令:javascript

for (let i=0; i< 10; i++) {
    //..
    }
    console.log(i) // ReferenceError: i is not defined

由於計數器 i 只在 for 循環體內有效,在循環體外引用就會報錯。java

for循環有一個特別之處,設置循環變量的那部分是一個父做用域,而循環體內是一個單獨的子做用域。es6

for(let i =0; i< 3; i++) {
    	let i = 'abc';
    	console.log(i);
    }
    // abc
    // abc
    // abc

上面代碼輸出了 3 次 abc, 這代表函數內部的變量 i 和循環變量 i 不在同一個做用域,有各自獨立的做用域;編程

特性1- 沒有變量提高和暫時性死區

咱們知道, var 聲明的變量會存在變量提高現象,可是 let 不會,let 聲明的變量必定在聲明後使用。不然報錯。好比:數組

// es5
    console.log(i); // undefined
    var i = 10;
	// es6
    console.log(j);// ReferenceError
    let j = 10;

只要塊級做用域內存在 let 和 const 命令,它所聲明的變量就「綁定」在這個區域,再也不受外部的影響。凡是在聲明以前就使用這些變量,就會報錯,這種稱爲「暫時性死區(TDZ)「;瀏覽器

TDZ的本質是隻要進入當前做用域,所要使用的變量就已經存在了,可是不可獲取,只有等到聲明變量的那一行代碼出現,才能夠獲取和使用該變量。數據結構

let i = 5;
    if(true) {
    	console.log(i);// Uncaught ReferenceError: i is not defined
    	let i=10;
    }

雖然全局做用域內有 i 這個變量,可是局部做用域裏用 let 聲明瞭一個同名變量,因此最後 i 就被綁定到局部做用域裏,它未聲明就使用,因此會報錯。ide

這樣的設計是爲了讓你們養成良好的編程習慣,變量必定要在聲明以後使用。不然就報錯。函數

特性2 - 不容許重複聲明

let不容許在相同做用域內,重複聲明同一個變量;es5

function fuc() {
      let a= 10;
      let a = 1;
    }// 報錯
    function func () {
    	let a= 10;
    	{
    	  let a = 1;
    	}
    }// 不報錯,不屬於同一做用域

爲何須要塊級做用域?

es5 只有全局做用域和函數做用域,沒有塊級做用域,這產生不少不合理的場景。

場景1,內層變量可能會覆蓋外層變量

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

if 代碼塊的外部使用外層的 tmp 變量,內部使用內層的 tmp 變量,可是。函數 f 執行後,輸出爲undefined;緣由在於變量提高致使的 tmp 變量覆蓋了外層的 tmp 變量;

場景2, 用來計數的循環變量泄露爲全局變量

var  s = 'hello';
    for(var i = 0; i < s.length; i++) {
    	console.log(i);
    }
    conole.log(i);

這裏,i 只是用來控制循環, 可是它沒有消失,泄露成了全局變量。

塊級做用域中的函數聲明

函數能不能在塊級做用域中聲明?

es5 規定,函數只能在頂層做用域和函數做用域之中聲明,不能在塊級做用域中聲明。

function f() { console.log('outside');}
    (function () {
    	if(false) {
    	  // 重複聲明一次函數
    	  function () { console.log('inside');}
    	}
    	f();
    }());

這串代碼在 es5 中運行,照規定來講是非法的,可是爲了兼容,仍是支持在塊級做用域中聲明函數,所以會獲得’inside'; 由於在 if 中聲明的函數會被提高到函數頭部,實際執行的代碼爲:

function f() { console.log('outside');}
    (function () {
    	function f() {console.log('inside');}
    	if (false) {
    	}
    	f();
    }());

在 es6中 執行會怎麼樣?會報錯

es6規定,函數能夠在塊級做用域內聲明。函數聲明的語句相似於let,在塊級做用域以外不能夠引用。

  • 容許在塊級做用域內聲明函數
  • 函數聲明相似於 var, 即會提高到全局做用域或函數做用域的頭部
  • 函數聲明還會提高到所在的塊級做用域的頭部
  • 只在使用大括號的狀況下成立

上面的代碼在符合es6的瀏覽器中,實際運行的是:

function f() { console.log('outside');}
    (function () {
    	var f = undefined;
    	if (false) {
    	  function f() {console.log('inside');}
    	}
    	f();
    }());

因此咱們應該避免在塊級做用域內聲明函數,若是須要,函數聲明應該寫成函數表達式,如

{
    	let a='haha';
    	let f = function () {
    	return a;
    	}
    }

塊級做用於域的返回值

塊級做用域不會返回值,咱們能夠將塊級做用域變爲表達式。在 {} 以前加上do, 而後就會返回內部最後執行的表達式的值。不過如今這只是個提案,如今這樣寫 do是瀏覽器沒法解析的。

let x = do {
    	let t = f();
    	t*t+1;
    }

const 的本質

const定義的是常量,它不是指變量的值不能改動,而是變量指向的那個內存地址不能改動。對於簡單類型的數據,值就保存在變量指向的那個內存地址,所以等同於常量,而符合類型的數據(數組和對象),變量指向的內存地址,保存的只是一個指針, const只能保證這個指針式固定的,而它指向的數據結構是不可控的。

總結

let 和 const 的特性有:

  • 只在本身的塊做用域內有效;塊做用域指的是{}。
  • 存在」暫時性死區「(TDZ),
  • 只能在聲明以後使用
  • 不存在變量提高;
相關文章
相關標籤/搜索