<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>