<div id="cnblogs_post_body" class="blogpost-body"><p>本系列是在平時閱讀、學習、實際項目中有關於es6中的新特性、用發的簡單總結,目的是記錄以備往後溫習;本系列預計包含let/const、箭頭函數、解構、經常使用新增方法、Symbol、Set&Map、Proxy、reflect、Class、Module、Iterator、Promise、Generator、async/await</p> <p>let/const爲咱們帶來了什麼?</p> <p><strong><span style="font-size: 18px;">let</span></strong></p> <ol> <li><span style="font-size: 16px;"><span style="font-size: 16px;"><strong>約束變量提高</strong></span></span> <div class="cnblogs_code"> <pre>(<span style="color: #0000ff;">function</span><span style="color: #000000;"> foo() { console.log(a); let a </span>= 1<span style="color: #000000;">; })();javascript
</span><span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught ReferenceError: a is not defined</span></pre>html
</div> <p>總結下來就是一句: 在變量使用以前,必須先要聲明,變量聲明永遠在使用以前。</p> </li> <li><span style="font-size: 16px;"><span style="font-size: 16px;"><strong>帶來了塊級做用域</strong></span></span> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre><span style="color: #008000;">//</span><span style="color: #008000;"> es5</span> (<span style="color: #0000ff;">function</span><span style="color: #000000;">(){ </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">false</span><span style="color: #000000;">) { </span><span style="color: #0000ff;">var</span> temp = 1<span style="color: #000000;">; } console.log(temp); </span><span style="color: #008000;">//</span><span style="color: #008000;"> undefined</span> <span style="color: #000000;"> })();java
</span><span style="color: #008000;">//</span><span style="color: #008000;"> es6</span> (<span style="color: #0000ff;">function</span><span style="color: #000000;">(){ </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">false</span><span style="color: #000000;">) { let temp </span>= 1<span style="color: #000000;">; } console.log(temp); </span><span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught ReferenceError: temp is not defined</span> })();</pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>從代碼中咱們能夠很清晰看到es6的let的塊級做用域,那麼塊級做用域有什麼應用呢?舉個例子:</p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre><span style="color: #0000ff;">var</span> fnArr =<span style="color: #000000;"> []; </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">var</span> i = 0; i < 5; i++<span style="color: #000000;">) { fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(i); }); } fnArr[</span>0](); <span style="color: #008000;">//</span><span style="color: #008000;"> 5</span> fnArr[1](); <span style="color: #008000;">//</span><span style="color: #008000;"> 5</span> fnArr[2](); <span style="color: #008000;">//</span><span style="color: #008000;"> 5</span> fnArr[3](); <span style="color: #008000;">//</span><span style="color: #008000;"> 5</span> fnArr[4](); <span style="color: #008000;">//</span><span style="color: #008000;"> 5</span> console.log(i); <span style="color: #008000;">//</span><span style="color: #008000;"> 5</span></pre> <div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>若是沒有仔細分析,執行的結果是否是有些出乎意料呢? 是的,咱們本意在for循環內部使用的變量i被泄露成了全局變量,並且在for循環的每一次循環,變量i並無被從新聲明,實際上數組fnArr中保存的每個函數中引用的都是同一個變量i,因此才致使瞭如今的結果,那怎麼讓代碼按照咱們最初的想法運行呢?來看es5中經常使用的解法</p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre><span style="color: #0000ff;">var</span> fnArr1 =<span style="color: #000000;"> []; </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">var</span> i = 0; i < 5; i++<span style="color: #000000;">) { (</span><span style="color: #0000ff;">function</span><span style="color: #000000;">(j) { fnArr1.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(j); }); })(i) } fnArr1[</span>0](); <span style="color: #008000;">//</span><span style="color: #008000;"> 0</span> fnArr1[1](); <span style="color: #008000;">//</span><span style="color: #008000;"> 1</span> fnArr1[2](); <span style="color: #008000;">//</span><span style="color: #008000;"> 2</span> fnArr1[3](); <span style="color: #008000;">//</span><span style="color: #008000;"> 3</span> fnArr1[4](); <span style="color: #008000;">//</span><span style="color: #008000;"> 4</span> console.log(i); <span style="color: #008000;">//</span><span style="color: #008000;"> 5</span></pre> <div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>看起來是解決了,這裏實際上用到了閉包的方法,fnArr1中每一項函數引用的j都是當前循環時i的一個副本,這樣就解決了前面的問題,可是還有一個問題: 變量i仍然隱式得泄露到了全局</p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre><span style="color: #0000ff;">var</span> fnArr1 =<span style="color: #000000;"> []; </span><span style="color: #0000ff;">for</span>(let i = 0; i < 5; i++<span style="color: #000000;">) { fnArr1.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(i); }); } fnArr1[</span>0](); <span style="color: #008000;">//</span><span style="color: #008000;"> 0</span> fnArr1[1](); <span style="color: #008000;">//</span><span style="color: #008000;"> 1</span> fnArr1[2](); <span style="color: #008000;">//</span><span style="color: #008000;"> 2</span> fnArr1[3](); <span style="color: #008000;">//</span><span style="color: #008000;"> 3</span> fnArr1[4](); <span style="color: #008000;">//</span><span style="color: #008000;"> 4</span> console.log(i); <span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught ReferenceError: i is not defined</span></pre> <div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>OK,問題解決了,僅僅是將’var‘替換成了let,這就是let帶來的便利。</p> </li> <li><span style="font-size: 16px;"><span style="font-size: 16px;"><strong>產生暫時性死區&禁止重複聲明</strong></span></span> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre><span style="color: #008000;">//</span><span style="color: #008000;"> 什麼是禁止重複聲明呢? 先不給書面解釋,來看一個es5中常常的寫法</span> (<span style="color: #0000ff;">function</span><span style="color: #000000;">() { </span><span style="color: #0000ff;">var</span> temp = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">var</span> temp = 2<span style="color: #000000;">; </span><span style="color: #0000ff;">var</span> temp = <span style="color: #0000ff;">function</span><span style="color: #000000;">() { </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">; }; })();</span></pre> <div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>上面這段代碼執行沒有任何問題,最終temp被賦值爲一個函數</p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre>(<span style="color: #0000ff;">function</span><span style="color: #000000;">() { let temp </span>= 1<span style="color: #000000;">; </span><span style="color: #0000ff;">var</span> temp = 2; <span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught SyntaxError: Identifier 'temp' has already been declared</span> <span style="color: #0000ff;">var</span> temp = <span style="color: #0000ff;">function</span><span style="color: #000000;">() { </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">; }; })();</span></pre> <div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>在第三行時就拋出了一個錯誤:temp已經被聲明,是的,let聲明過的變量,是不容許再次被聲明的,再給幾個例子鞏固一下:</p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre>(<span style="color: #0000ff;">function</span><span style="color: #000000;">() { </span><span style="color: #0000ff;">var</span> temp = 2<span style="color: #000000;">; </span><span style="color: #0000ff;">var</span> temp = <span style="color: #0000ff;">function</span><span style="color: #000000;">() { </span><span style="color: #0000ff;">return</span> 1<span style="color: #000000;">; }; let temp </span>= 1; <span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught SyntaxError: Identifier 'temp' has already been declared</span> <span style="color: #000000;"> })();es6
(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) { let temp </span>= 1<span style="color: #000000;">; </span><span style="color: #0000ff;">var</span> temp = 2; <span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught SyntaxError: Identifier 'temp' has already been declared</span>
<span style="color: #000000;"> } })();數組
(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) { let temp </span>= 1<span style="color: #000000;">; </span><span style="color: #0000ff;">function</span> temp() { <span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught SyntaxError: Identifier 'temp' has already been declared</span> <span style="color: #0000ff;">return</span> 1<span style="color: #000000;">; } } })();</span></pre>閉包
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>看出來了嗎?只要是在let聲明所在的做用域,就不容許再次聲明同名變量(包括函數聲明)</p> <div class="cnblogs_code"> <pre><span style="color: #0000ff;">var</span> foo = 1<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(<span style="color: #0000ff;">true</span><span style="color: #000000;">) { foo </span>= 2; <span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught ReferenceError: foo is not defined</span> <span style="color: #000000;"> let foo; }</span></pre> </div> <p>看到let的’霸道‘了吧?只要在let所在的做用域,同名的變量就會被let佔有,不容許重複聲明,同時也要遵照let的規則</p> </li> <li><span style="font-size: 16px;"><span style="font-size: 16px;"><strong>全局變量再也不做爲window對象的屬性</strong></span></span> <div class="cnblogs_code"> <pre><span style="color: #0000ff;">var</span> foo = 1<span style="color: #000000;">; (</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { bar </span>= 2<span style="color: #000000;">; })(); window.foo; </span><span style="color: #008000;">//</span><span style="color: #008000;"> 1</span> window.bar; <span style="color: #008000;">//</span><span style="color: #008000;"> 2</span></pre> </div> <p>是的,es5中,全局變量(包括意外泄露的)都將自動被添加爲window對象的屬性</p> <div class="cnblogs_code"> <pre>let foo = 1<span style="color: #000000;">;async
window.foo; </span><span style="color: #008000;">//</span><span style="color: #008000;"> undefined</span></pre>函數
</div> <p>一切盡在不言中。。。</p> </li> </ol> <p><strong><span style="font-size: 18px;">const</span></strong></p> <ol> <li><span style="font-size: 14px;"><span style="font-size: 14px;">let所擁有的特性,const都有,同時const還有一條:const聲明的變量必須進行初始化,而且不能再被從新賦值</span></span> <div class="cnblogs_code"> <pre>const temp = 1<span style="color: #000000;">; temp </span>= 2; <span style="color: #008000;">//</span><span style="color: #008000;"> Uncaught TypeError: Assignment to constant variable.</span></pre> </div> <p>注意是不能被從新賦值,這樣是比較準確的,其實const聲明的變量是能夠被修改的,當const聲明的變量被初始化爲複雜數據類型時,const聲明的變量就是可變的,至於爲何,本身理解嘍(變量標識符中保存的只是複雜數據類型內存地址而已。。。)</p> <div class="cnblogs_code"> <pre>const temp =<span style="color: #000000;"> {}; temp.foo </span>= 'aa'; <span style="color: #008000;">//</span><span style="color: #008000;"> 這裏沒問題</span> temp = {foo: 'aa'}; <span style="color: #008000;">//</span><span style="color: #008000;"> 這裏就會拋出異常</span></pre> </div> <p> </p> </li> </ol> <p><span style="font-size: 18px;"><strong>for循環中的變量聲明</strong></span></p> <p><span style="font-size: 14px;">前面在記錄let塊級做用域的時候,咱們使用了一個for循環的例子,這裏咱們不妨試着解析一下for循環的執行過程</span></p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre><span style="color: #0000ff;">var</span> fnArr =<span style="color: #000000;"> []; </span><span style="color: #0000ff;">for</span>(<span style="color: #0000ff;">var</span> i = 0; i < 3; i++<span style="color: #000000;">) { fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(i); }); }post
</span><span style="color: #008000;">//</span><span style="color: #008000;"> 僞代碼</span> <span style="color: #0000ff;">var</span><span style="color: #000000;"> fnArr; fnArr </span>=<span style="color: #000000;"> []; { </span><span style="color: #0000ff;">var</span><span style="color: #000000;"> i; i </span>= 0<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(i < 3<span style="color: #000000;">) { fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(i); }) } i</span>++<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(i < 3<span style="color: #000000;">) { fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(i); }); } i</span>++<span style="color: #000000;">; ... }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>這裏惋惜清晰得看到全部的i都是一個i。。。那使用了let之後呢?</p> <div class="cnblogs_code"><div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div> <pre><span style="color: #0000ff;">var</span> fnArr =<span style="color: #000000;"> []; </span><span style="color: #0000ff;">for</span>(let i = 0; i < 3; i++<span style="color: #000000;">) { fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(i); }); }學習
</span><span style="color: #008000;">//</span><span style="color: #008000;"> 僞代碼</span> <span style="color: #0000ff;">var</span><span style="color: #000000;"> fnArr; fnArr </span>=<span style="color: #000000;"> []; { let i; i </span>= 0<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(i < 3<span style="color: #000000;">) { let i </span>=<span style="color: #000000;"> i; fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(i); }) } i</span>++<span style="color: #000000;">; </span><span style="color: #0000ff;">if</span>(i < 3<span style="color: #000000;">) { let i </span>=<span style="color: #000000;"> i; fnArr.push(</span><span style="color: #0000ff;">function</span><span style="color: #000000;">() { console.log(i); }); } i</span>++<span style="color: #000000;">; ... }</span></pre>
<div class="cnblogs_code_toolbar"><span class="cnblogs_code_copy"><a href="javascript:void(0);" onclick="copyCnblogsCode(this)" title="複製代碼"><img src="//common.cnblogs.com/images/copycode.gif" alt="複製代碼"></a></span></div></div> <p>是否是看出點名堂?其實咱們徹底能夠這樣理解,在每一次循環中都從新聲明瞭i,而且被賦值爲外層i的當前值。(注意啊,這裏只是僞代碼,便於理解,實際中let i = i是會拋出異常的)</p></div>