ES6 let和count


1、let命令用法:

  a、let用來聲明變量,類似var,但用let聲明的變量,只能在其代碼塊中引用,相當於私有變量,不會被外界所獲取:

    function fn(){

      let a = 1

      console.log(a)      這里可以直接調用

    }

    console.log(a)  在函數外面訪問輸出就會報錯

    以后在for循環中比較適合用let:

    var a = [];

    for (var i = 0; i < 10; i++)

      a[i] = function ();

        console.log(i)

      }

     }

   a[6]();這里會輸出10

    用var聲明的i相當於全局變量,在全局范圍內都有效,所以全局只有一個變量i。每一次循環,變量i的值都會發生改變,而循環內被賦給數組a的函數內部的console.log(i),里面的i指向的就是全局的i。也就是說,所有數組a的成員里面的i,指向的都是同一個i,導致運行時輸出的是最后一輪的i的值,也就是10。

    把var換成let,最后輸出的結果就是6

 

    還有在fou循環中,設置循環的部分是父作用域,在循環體內是子作用域:

    for ( let i = 0; i < 10; i++){

      let i = 'aaa';

      console.log(i)

    }

    最終輸出10次'aaa',這是因為聲明在不同塊內,相互是不一樣的。

  b、不存在變量提升了

    console.log(a)  輸出結果是undefind

    var a = 1;

    console.log(b)  報錯

    let b = 1;

    這是因為用var聲明變量之前調用,因為變量提升的原因,即輸出的時候,變量已經存在,但沒有給a賦值,所以輸出undefined,但用let聲明變量只會在聲明后存在,之前調用就會報錯。

  c、暫時性死區

    let tem = 'abc';

    if(true){

      console.log(tem);

      let tem;

    }

    這是就會報錯,因為如果在一個塊中存在let一個變量,那在let這個變量之前,不能出現這個變量!ES6明確規定,如果區塊中存在letconst命令,這個區塊對這些命令聲明的變量,從一開始就形成了封閉作用域。凡是在聲明之前就使用這些變量,就會報錯。在代碼塊內,使用let命令聲明變量之前,該變量都是不可用的。這在語法上,稱為“暫時性死區”(temporal dead zone,簡稱 TDZ)。

    所以,在這個區域內使用tepyof就不太准確了。比如:

    tepyof x;

    let x;

    這時就會報錯,而沒有聲明的變量反而不會報錯:

    tepyof obj;   undefined

    所以一定要在聲明變量再使用!!!

    let x = x;

    這樣也是會報錯的,使用let聲明變量時,只要變量在還沒有聲明完成前使用,就會報錯。上面這行就屬於這個情況,在變量x的聲明語句還沒有執行完成前,就去取x的值,導致報錯”x 未定義“。

    

    ES6 規定暫時性死區和letconst語句不出現變量提升,主要是為了減少運行時錯誤,防止在變量聲明前就使用這個變量,從而導致意料之外的行為。這樣的錯誤在 ES5 是很常見的,現在有了這種規定,避免此類錯誤就很容易了。

    總之,暫時性死區的本質就是,只要一進入當前作用域,所要使用的變量就已經存在了,但是不可獲取,只有等到聲明變量的那一行代碼出現,才可以獲取和使用該變量。  

  d、不允許重復聲明

    function fn(){

      let a = 1;

      var a = 2;(或者let a = 3;)

    }    報錯

    function fn2 (arg){

      let arg = 2;

    }    報錯

    這樣的操作都會報錯,在同一個作用域下,不允許重復聲明一個變量,也不允許變量名和參數名相同

2、塊級作用域

  以前只有全局作用域和函數作用域,現在增加了塊級作用域,為什么增加塊級作用域?

  原因一:內層變量會覆蓋掉外層變量

    var time = new Date();

    function times () {

      console.log(time);

      if(false){

        var time = 'hello';

      }

    }

  times();  

  這時輸出的是undefined;因為變量提升的原因,函數作用域中存在私有變量time,但沒有賦值,所以就會覆蓋掉全局變量。

  原因二:用來計數的循環變量泄漏成全局變量

  var str = 'hello';

  for (var i = 0; i < str.length; i++){

    console.log(str[i]);

  }

  console.log(i);

  在外層也會訪問到變量i;這樣i就變成來全局變量。

  let為javascript提供來塊級作用域:

  function fn(){

    let n = 5;

    if(true){

      n = 10;

    }

    console.log(n);

  }

  這時輸出的還是 5 ,雖然內層和外層都定義了n,但外層不受內層的影響。如果換成var,輸出結果就是 10

  ES6允許塊級任意嵌套:

  {{{{{let n = 1;}}}}}   這是5層塊級作用域,外層的訪問不到內層的;

  {{{

    console.log(n);

    {let n = 2;}

  }}}    這是就會報錯。

  {{{

    let n = 1;

    {let n = 2}

  }}}   外層和內層允許存在相同的變量名,相互不受影響。

  塊級作用域的出現,使得自執行函數(IIFE)不再必要了:

  IIFE:

  (function () {...})()

  塊級作用域:

  {let...}

 

  do 表達式

 

  本質上,塊級作用域是一個語句,將多個操作封裝在一起,沒有返回值。

 

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

 

  上面代碼中,塊級作用域將兩個語句封裝在一起。但是,在塊級作用域以外,沒有辦法得到t的值,因為塊級作用域不返回值,除非t是全局變量。

 

  現在有一個提案,使得塊級作用域可以變為表達式,也就是說可以返回值,辦法就是在塊級作用域之前加上do,使它變為do表達式,然后就會返回內部最后執行的表達式的值。

 

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

 

  上面代碼中,變量x會得到整個塊級作用域的返回值(t * t + 1)。

 

3、const基本用法:

  const聲明常量,一旦聲明,其值將不能改變。所以也就意味着,一旦使用const聲明變量就要及時賦值,不能先聲明再賦值。

  a、const和let一樣,只在聲明的作用域中起作用。

  b、同樣不提升,只能在聲明后才能使用。

  c、同樣不能重復聲明。

4、本質

  const的本質就是引用地址不能變,但對於地址內部的信息是可以修改的,尤其是聲明的對象和數組這樣引用類型的:

  const arr = [];

  arr.lenght 可以執行;

  arr.push(23) 可以執行

  arr = ['abs']  報錯

  const str = {};

  str.prop = 'abc' 可執行

  str = {}  指向另一個對象就會報錯

  如果真的要凍結對象,需要用到 Object.freeze方法

  const str = Object.freeze({});

  str.prop = 'abc'  在嚴格模式下就會報錯,在非嚴格模式下不起作用。

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

  var constantize = (obj) => {

    Object.freeze(obj);

   Object.keys(obj).forEach( (key, i) => {

    if ( typeof obj[key] === 'object' ) {

      constantize( obj[key] );

    }

   });

  };

 

ES6除了以前的var和function聲明變量外,新增了let和const聲明變量,后面還有import和class,后期再補充。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM