<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>随笔</title>
  
  
  <link href="/atom.xml" rel="self"/>
  
  <link href="https://liushuai97.github.io/"/>
  <updated>2020-08-28T08:45:07.529Z</updated>
  <id>https://liushuai97.github.io/</id>
  
  <author>
    <name>前端菜鸟</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>你不知道的HTML</title>
    <link href="https://liushuai97.github.io/2020/08/28/%E4%BD%A0%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84HTML/"/>
    <id>https://liushuai97.github.io/2020/08/28/你不知道的HTML/</id>
    <published>2020-08-28T06:58:29.000Z</published>
    <updated>2020-08-28T08:45:07.529Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="crossorigin-”anonymous”-跨域属性"><a href="#crossorigin-”anonymous”-跨域属性" class="headerlink" title="crossorigin=”anonymous” 跨域属性"></a>crossorigin=”anonymous” 跨域属性</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;meta charset=&quot;utf-8&quot;&gt;</span><br><span class="line">&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;</span><br><span class="line">&lt;title&gt;你不知道的HTML&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line"> &lt;!-- crossorigin=&quot;anonymous&quot; 是否需要跨域 --&gt;</span><br><span class="line">&lt;img crossorigin=&quot;anonymous&quot; src=&quot;ok.jpg&quot; /&gt;</span><br><span class="line">&lt;script type=&quot;text/javascript&quot; charset=&quot;utf-8&quot;&gt;</span><br><span class="line">// 利用图像测试用户访问网速</span><br><span class="line">var s = Date.now();</span><br><span class="line">var img = new Image();</span><br><span class="line">img.crossorigin = &quot;anonymous&quot;;</span><br><span class="line">img.src = &apos;http://www.xxx.com/ok.png&apos;; // 1*1 3kb</span><br><span class="line">img.onload = function () &#123;</span><br><span class="line">var e = Date.now();</span><br><span class="line">var w = 4 / e - s; // 1-1000</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><h4 id="image-获取用户访问网速-上报埋点数据"><a href="#image-获取用户访问网速-上报埋点数据" class="headerlink" title="image 获取用户访问网速 上报埋点数据"></a>image 获取用户访问网速 上报埋点数据</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">// 系统性能监控平台 系统的BUG监控平台  上报数据  页面埋点</span><br><span class="line">var img = new Image();</span><br><span class="line">img.crossorigin = &quot;anonymous&quot;;</span><br><span class="line">img.src = &apos;http://www.xxx.com/ok.git?...&apos;;</span><br><span class="line">// GET方式提交的数据最多只能是1024字节</span><br><span class="line">// 不使用Ajax，因为Ajax是具有实时性的，并且超过5个Ajax请求会导致并发的问题产生</span><br><span class="line">// Dom render 时触发 click</span><br></pre></td></tr></table></figure><h4 id="css-远程攻击漏洞"><a href="#css-远程攻击漏洞" class="headerlink" title="css 远程攻击漏洞"></a>css 远程攻击漏洞</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;meta charset=&quot;utf-8&quot;&gt;</span><br><span class="line">&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;</span><br><span class="line">&lt;title&gt;css 远程攻击漏洞&lt;/title&gt;</span><br><span class="line">&lt;style type=&quot;text/css&quot;&gt;</span><br><span class="line">.test &#123;</span><br><span class="line">color: expresssion(alert(&apos;xss&apos;));</span><br><span class="line">/*可以跨域访问远程执行脚步，例如：外框*/</span><br><span class="line">background: url(&apos;javascript:alert(&apos;123&apos;)&apos;);</span><br><span class="line">&#125;</span><br><span class="line">.test::content&#123;</span><br><span class="line">content: url(&apos;javascript:alert(&apos;123&apos;)&apos;);</span><br><span class="line">&#125;</span><br><span class="line">&lt;/style&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;!-- html数量必须控制 --&gt;</span><br><span class="line">&lt;!-- </span><br><span class="line">dom元素越多导致网页加载速度越慢  </span><br><span class="line">:after</span><br><span class="line">:before</span><br><span class="line">box-shadow</span><br><span class="line">--&gt;</span><br><span class="line">&lt;!-- CSS 依赖 GPU 渲染 --&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><ul><li>xss攻击</li></ul><p>非持久型xss攻击：顾名思义，非持久型xss攻击是一次性的，仅对当次的页面访问产生影响。非持久型xss攻击要求用户访问一个被攻击者篡改后的链接，用户访问该链接时，被植入的攻击脚本被用户游览器执行，从而达到攻击目的。</p><p>持久型xss攻击：持久型xss，会把攻击者的数据存储在服务器端，攻击行为将伴随着攻击数据一直存在。</p><ul><li>类别</li></ul><p>反射型：经过后端，不经过数据库</p><p>存储型：经过后端，经过数据库</p><p>DOM：不经过后端,DOM—based XSS漏洞是基于文档对象模型Document Objeet Model,DOM的一种漏洞,dom - xss是通过url传入参数去控制触发的。</p><h4 id="iframe对远程localStorage扩容"><a href="#iframe对远程localStorage扩容" class="headerlink" title="iframe对远程localStorage扩容"></a>iframe对远程localStorage扩容</h4><ul><li>iframe.html</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;meta charset=&quot;utf-8&quot;&gt;</span><br><span class="line">&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;</span><br><span class="line">&lt;title&gt;iframe对远程localStorage扩容&lt;/title&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;!-- 跨域  JSONP --&gt;</span><br><span class="line">&lt;script src=&quot;http://www.xxx.com/a.php&quot;&gt;&lt;/script&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">const hi = (data) =&gt; &#123;</span><br><span class="line">alert(data);</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"></span><br><span class="line">&lt;!-- canvas  js to png  代码压缩进图片并实现跨域执行--&gt;</span><br><span class="line">&lt;img src=&quot;图片（代码）&quot; alt=&quot;&quot;/&gt;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&lt;!-- iframe 通信--&gt;</span><br><span class="line">&lt;!-- 对本服务器的localStorage进行扩容  同域同源策略--&gt;</span><br><span class="line"></span><br><span class="line">协议不同</span><br><span class="line">http -&gt; scoect;</span><br><span class="line"></span><br><span class="line">端口不同</span><br><span class="line">localhost:80 -&gt; localhost:81;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">&lt;!-- document.domain = &apos;baidu.com&apos; --&gt;</span><br><span class="line">&lt;iframe src=&quot;localhost/storage.html&quot; frameborder=&quot;0&quot;&gt;&lt;/iframe&gt;</span><br><span class="line">&lt;script type=&quot;text/javascript&quot;&gt;</span><br><span class="line">window.framesp[0].postMessage(&apos;key&apos;, &apos;val&apos;);</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><ul><li>storage.html</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;meta charset=&quot;utf-8&quot;&gt;</span><br><span class="line">&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;</span><br><span class="line">&lt;title&gt;&lt;/title&gt;</span><br><span class="line">&lt;link rel=&quot;stylesheet&quot; href=&quot;&quot;&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;script&gt;</span><br><span class="line">window.addEventListener(&apos;key&apos;, (e) =&gt; &#123;</span><br><span class="line">if (e.source !== window.parent ) &#123;</span><br><span class="line">return ;</span><br><span class="line">&#125;</span><br><span class="line">localStorage.setItem(e.data.key, e.data.value);</span><br><span class="line">&#125;)</span><br><span class="line">&lt;/script&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><h4 id="HTML语义化"><a href="#HTML语义化" class="headerlink" title="HTML语义化"></a>HTML语义化</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br></pre></td><td class="code"><pre><span class="line">&lt;!DOCTYPE html&gt;</span><br><span class="line">&lt;html&gt;</span><br><span class="line">&lt;head&gt;</span><br><span class="line">&lt;meta charset=&quot;utf-8&quot;&gt;</span><br><span class="line">&lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot;&gt;</span><br><span class="line">&lt;title&gt;HTML语义化&lt;/title&gt;</span><br><span class="line">&lt;link rel=&quot;stylesheet&quot; href=&quot;&quot;&gt;</span><br><span class="line">&lt;/head&gt;</span><br><span class="line">&lt;body&gt;</span><br><span class="line">&lt;&lt;label for=&quot;id&quot;&gt;&lt;input type=&quot;&quot; name=&quot;&quot; value=&quot;&quot;&gt;&lt;/label&gt;</span><br><span class="line">&lt;ol&gt;</span><br><span class="line">&lt;li&gt;&lt;/li&gt;</span><br><span class="line">&lt;/ol&gt;</span><br><span class="line">&lt;dl&gt;</span><br><span class="line">&lt;dt&gt;&lt;/dt&gt;</span><br><span class="line">&lt;dd&gt;&lt;/dd&gt;</span><br><span class="line">&lt;/dl&gt;</span><br><span class="line">&lt;ul&gt;</span><br><span class="line">&lt;li&gt;&lt;/li&gt;</span><br><span class="line">&lt;/ul&gt;</span><br><span class="line">&lt;table&gt;</span><br><span class="line">&lt;thead&gt;</span><br><span class="line"></span><br><span class="line">&lt;/thead&gt;</span><br><span class="line">&lt;tbody&gt;</span><br><span class="line"></span><br><span class="line">&lt;/tbody&gt;</span><br><span class="line">&lt;tfooter&gt;</span><br><span class="line"></span><br><span class="line">&lt;/tfooter&gt;</span><br><span class="line">&lt;/table&gt;</span><br><span class="line">&lt;!-- 侧重使用H5语义化标签 html5.js--&gt;</span><br><span class="line">&lt;header&gt;</span><br><span class="line">&lt;nav&gt;&lt;/nav&gt;</span><br><span class="line">&lt;/header&gt;</span><br><span class="line">&lt;article&gt;</span><br><span class="line">&lt;hgroup&gt;</span><br><span class="line">&lt;h1&gt;&lt;/h1&gt;</span><br><span class="line">&lt;/hgroup&gt;</span><br><span class="line">&lt;section&gt;</span><br><span class="line"></span><br><span class="line">&lt;/section&gt;</span><br><span class="line">&lt;aside&gt;</span><br><span class="line"></span><br><span class="line">&lt;/aside&gt;</span><br><span class="line">&lt;/article&gt;</span><br><span class="line">&lt;footer&gt;</span><br><span class="line">&lt;address&gt;&lt;/address&gt;</span><br><span class="line">&lt;/footer&gt;</span><br><span class="line">&lt;/body&gt;</span><br><span class="line">&lt;/html&gt;</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;crossorigin-”anonymous”-跨域属性&quot;&gt;&lt;a href=&quot;#crossorigin-”anonymous”-跨域属
      
    
    </summary>
    
    
      <category term="HTML" scheme="https://liushuai97.github.io/categories/HTML/"/>
    
    
      <category term="HTML" scheme="https://liushuai97.github.io/tags/HTML/"/>
    
  </entry>
  
  <entry>
    <title>TS基础语法</title>
    <link href="https://liushuai97.github.io/2020/03/19/TS%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95/"/>
    <id>https://liushuai97.github.io/2020/03/19/TS基础语法/</id>
    <published>2020-03-19T08:04:12.000Z</published>
    <updated>2020-08-27T01:24:13.443Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="TypeScript入门"><a href="#TypeScript入门" class="headerlink" title="TypeScript入门"></a>TypeScript入门</h4><p>微软开发的编程语言，是JavaScrip的超集，遵循了ES6的语法。</p><p>前置知识：</p><p>· 理解ES5、6，JavaScript,TypeScript的概念和关系<br>· 有基础的JavaScript开发经验</p><p>TypeScript的优势</p><p>· 支持ES6规范<br>· 强大的IDE支持<br>· Angular2的开发语言</p><h4 id="搭建TypeScript开发环境"><a href="#搭建TypeScript开发环境" class="headerlink" title="搭建TypeScript开发环境"></a>搭建TypeScript开发环境</h4><p><code>npm install -g typescript</code></p><h4 id="手动配置Webapck"><a href="#手动配置Webapck" class="headerlink" title="手动配置Webapck"></a>手动配置Webapck</h4><p>因为webpack是基于nodejs环境下的，所以我们首先创建node项目</p><p><code>npm init | yarn init</code></p><p>创建完成后，执行全局安装命令</p><p><code>npm install -g webpack</code></p><p>紧接着执行nodejs项目依赖安装</p><p><code>npm install webpack --save | yarn add webpack --dev</code></p><h4 id="yran解决了什么？"><a href="#yran解决了什么？" class="headerlink" title="yran解决了什么？"></a>yran解决了什么？</h4><ul><li>离线模式</li></ul><p>已安装过的软件包，再次安装时不用再从网络下载</p><ul><li>依赖关系确定性</li></ul><p>每一台机器上针对同一个工程安装依赖时，生成的依赖关系顺序和版本是一致的</p><ul><li>更好的网络性能</li></ul><p>下载软件包时，会进行更好的排序，避免”请求瀑布”，最大限度提高网络利用率</p><ul><li>多注册来源处理</li></ul><p>所有的依赖包，不管是否被不同的库间接关联引用多少次，安装这个包时，只会从一个注册来源去安装，要么使用NPM，要么是Bower，防止出现混乱不一致。</p><ul><li>网络弹性处理</li></ul><p>安装依赖时，不会因为某个单次网络请求的失败导致整个安装挂掉。当请求失败时回进行自动重试</p><ul><li>扁平模式</li></ul><p>当关联依赖中包括对某个软件包的重复引用，在实际安装时将尽量避免重复的创建</p><h4 id="webpack-的意义？"><a href="#webpack-的意义？" class="headerlink" title="webpack 的意义？"></a>webpack 的意义？</h4><p>webpack获取带依赖的模块并产出与这些模块相对于的静态资源。</p><ul><li>webpack的目标：</li></ul><p>· 拆分依赖书成块并按需加载<br>· 让初始化加载时间更少<br>· 每一个静态资源应该是一个模块<br>· 能够集成第三方类库<br>· 适用于大型项目<br>· 能够定制模块打包的每一个部分</p><ul><li>Plugins(插件)</li></ul><p>webpack有着丰富的插件接口,这使得webpack非常的灵活</p><ul><li>Performance(性能)</li></ul><p>webpack使用异步I/O和多级缓存,这使得webpack在增量编译上极其快.</p><ul><li>Loader(装载机)</li></ul><p>webpack支持通过装载机预处理文件.这允许你处理任何静态资源(不仅仅是JavaScript),你可以很轻松的写出在Nodejs上运行的装载机.</p><ul><li>Suport(支持)</li></ul><p>webpack支持AMD和CommonJs模块样式.它巧妙的在你代码的AST中进行静态分析,它甚至还能处理简单的表达式,这样就允许你支持更多的类库.</p><ul><li>Code Splitting(代码拆分)</li></ul><p>webpack允许你将你的代码拆分成块,每块代码按需加载,这样就可以减少初始化加载时间.</p><ul><li>Optimizations(优化)</li></ul><p>webpack可以大量的优化来减少输出的大小,并使用hashes来实现请求缓存.</p><ul><li>Development Tools(开发工具)</li></ul><p>webpack支持SourceUrls和SourceMaps进行简单的调试.通过development middleware来监控文件和development server来自动刷新.</p><ul><li>Multiple targets(多个目标)</li></ul><p>webpack的主要目标是web,同时它也支持为nodejs和WebWorkers上的代码打包.</p><ul><li>Motivation(动机)</li></ul><p>现在的website正在慢慢演变为webapps:</p><p>· 越来越多的JavaScript代码被使用<br>· 现代浏览器提供了丰富的接口<br>· 更少的全页面重载，也就意味着单页面需要加载更多的代码.</p><p>这样的结果就是大量的代码会存在于client side.这样大量的代码就需要被组织.模块系统可以有效的管理你的代码.</p><h4 id="报错问题"><a href="#报错问题" class="headerlink" title="报错问题"></a>报错问题</h4><p>node-gyp 报错、 xcode-select报错</p><p>删除已经安装的CommandLineTools</p><p><code>xcode-select --install</code></p><p>数据源报错问题，可以切换淘宝源尝试 <code>npm install -g cnpm --registry=https://registry.npm.taobao.org</code></p><p>重新安装即可</p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;TypeScript入门&quot;&gt;&lt;a href=&quot;#TypeScript入门&quot; class=&quot;headerlink&quot; title=&quot;Typ
      
    
    </summary>
    
    
      <category term="TypeScript" scheme="https://liushuai97.github.io/categories/TypeScript/"/>
    
    
      <category term="TypeScript" scheme="https://liushuai97.github.io/tags/TypeScript/"/>
    
  </entry>
  
  <entry>
    <title>BFF架构代码实践</title>
    <link href="https://liushuai97.github.io/2019/11/30/BFF%E6%9E%B6%E6%9E%84%E4%BB%A3%E7%A0%81%E5%AE%9E%E8%B7%B5/"/>
    <id>https://liushuai97.github.io/2019/11/30/BFF架构代码实践/</id>
    <published>2019-11-30T02:24:33.000Z</published>
    <updated>2019-12-02T01:16:32.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:27 GMT+0800 (GMT+08:00) --><h4 id="前后端分离"><a href="#前后端分离" class="headerlink" title="前后端分离"></a>前后端分离</h4><ul><li>单体应用</li></ul><p>严重依赖后端</p><p>前端无法单独调试，开发效率低</p><p>前端不可避免遇到后台代码</p><p>后端本身会引发一些问题，如同步加载问题，如果是JSP第一次运行缓慢等</p><ul><li>半分离</li></ul><p>SPA是典型的前后端分离</p><p>在业务复杂的情况下，页面的渲染部分的代码非常负载，冗余严重</p><p>在Json返回的数据量较大的情况下，渲染缓慢</p><p>由于搜索引擎的爬虫无法爬下JS异步渲染的数据，SEO会存在一定的问题</p><p>业务时，一个页面可能要发起多次HTTP请求才能将页面渲染完毕，资源消耗严重</p><ul><li>彻底分离</li></ul><p>前端：负责View和Controller层</p><p>后端：只负责Model层、业务/数据处理等。</p><p>优点：</p><p>适配性提升</p><p>响应速度提升</p><p>性能得到提升</p><p>异步与模板统一</p><h4 id="前后端分离后的职责划分"><a href="#前后端分离后的职责划分" class="headerlink" title="前后端分离后的职责划分"></a>前后端分离后的职责划分</h4><p><img src="vm.png" alt="kyrie irving"></p><h4 id="传统应用的单端调用与多端调用"><a href="#传统应用的单端调用与多端调用" class="headerlink" title="传统应用的单端调用与多端调用"></a>传统应用的单端调用与多端调用</h4><ul><li>单端调用</li></ul><p>传统的应用内提供的接口是有业务针对性的<br>重构困难<br>高耦合度</p><ul><li>多端调用</li></ul><p>接口同时提供给web、移动端使用<br>移动端仅用来采集数据以及数据的展示<br>而web端大多数场景用来管理数据<br>不同断电的业务有所不同<br>每个端的接口复用度不会太高</p><h4 id="BFF初探"><a href="#BFF初探" class="headerlink" title="BFF初探"></a>BFF初探</h4><p>BFF即Backend For Frontend(服务于前端的后盾)，也就是服务器设计API时会考虑前端的使用，并在服务端直接进行业务逻辑的处理，又称为用户体验适配器，BFF只是一张逻辑分层，而非一种技术，虽然BFF是一个新名词，但它的理念由来已久。</p><p>概念上，把每个前端应用拆分两部分：客户端应用与服务端部分（BFF）。其中，BFF是面向特定用户体验的，由实现这部分UI的前端团队负责实现及维护。（即UI与对应的BFF由同一个团队负责）</p><p>从服务的角度看，BFF实际上是限制了单一服务所支持的消费者（指前端应用）数量，从而让他们更易于使用（更贴合前端需要）和更改，并帮助开发前端应用的团队保留更多的自主权。</p><p>应用：</p><p>访问控制：例如，服务中的权限控制，将所有服务中的权限控制集中在BFF层，使下层服务更加纯粹和独立</p><p>应用缓存：项目中时常存在一些需要缓存的临时数据，此时BFF作为业务的汇聚点，距离用户请求最近，遂将该缓存操作放在BFF层。</p><p>第三方入口：在业务中需要与第三交互时，将该交互放在BFF层，这样可以只暴露必要信息给第三方，从而便于控制第三方的访问。</p><h4 id="BFF与微服务"><a href="#BFF与微服务" class="headerlink" title="BFF与微服务"></a>BFF与微服务</h4><p>存在的缺点：</p><p>响应时间延迟（服务如果是内网之间，延迟时间较低）</p><p>编写起来较为浪费时间（因为在基础服务上添加的一层转发，所以会多写一部分代码）</p><p>业务异常处理（统一格式化业务异常的返回内容）</p><p>分布式事务（微服务的通病）</p><h4 id="微服务到底是什么"><a href="#微服务到底是什么" class="headerlink" title="微服务到底是什么"></a>微服务到底是什么</h4><p>微服务始于架构层面的设计模式</p><p>微服务的设计概念以业务功能为主</p><p>微服务独立提供对应的业务功能</p><p>微服务不拘泥与具体的实现语言</p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:27 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;前后端分离&quot;&gt;&lt;a href=&quot;#前后端分离&quot; class=&quot;headerlink&quot; title=&quot;前后端分离&quot;&gt;&lt;/a&gt;前后端分离&lt;
      
    
    </summary>
    
    
      <category term="Web" scheme="https://liushuai97.github.io/categories/Web/"/>
    
    
      <category term="Web" scheme="https://liushuai97.github.io/tags/Web/"/>
    
  </entry>
  
  <entry>
    <title>服务器免密登录</title>
    <link href="https://liushuai97.github.io/2019/11/29/%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%85%8D%E5%AF%86%E7%99%BB%E5%BD%95/"/>
    <id>https://liushuai97.github.io/2019/11/29/服务器免密登录/</id>
    <published>2019-11-29T02:29:33.000Z</published>
    <updated>2019-11-29T02:43:00.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="生成密钥"><a href="#生成密钥" class="headerlink" title="生成密钥"></a>生成密钥</h4><p>本地客户端生成公私钥 <code>ssh-keygen</code></p><h4 id="客户端配置"><a href="#客户端配置" class="headerlink" title="客户端配置"></a>客户端配置</h4><p><code>~/.ssh vim config</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"># config文件配置</span><br><span class="line"># 多主机配置</span><br><span class="line">Host name1-p</span><br><span class="line">HostName 服务器主机公网IP地址</span><br><span class="line">Port 默认22端口</span><br><span class="line"></span><br><span class="line">Host nam2-p</span><br><span class="line">HostName 服务器主机公网IP地址</span><br><span class="line">Port 6666</span><br><span class="line"></span><br><span class="line">Host nam3-p</span><br><span class="line">HostName 服务器主机公网IP地址</span><br><span class="line">Port 22</span><br><span class="line"></span><br><span class="line">Host *-p</span><br><span class="line">User root</span><br><span class="line">IdentityFile /Users/liu/.ssh/key_ssh</span><br><span class="line">Protocol 2</span><br><span class="line">Compression yes</span><br><span class="line">ServerAliveInterval 60</span><br><span class="line">ServerAliveCountMax 20</span><br><span class="line">LogLevel INFO</span><br></pre></td></tr></table></figure><h4 id="服务端配置"><a href="#服务端配置" class="headerlink" title="服务端配置"></a>服务端配置</h4><ol><li>修改配置</li></ol><p><code>vim /etc/ssh/sshd_config</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">HostKey /etc/ssh/ssh_host_rsa_key</span><br><span class="line">RSAAuthentication yes</span><br><span class="line">PubkeyAuthentication yes</span><br><span class="line">AuthorizedKeysFile      .ssh/authorized_keys　　#公钥文件存储位置</span><br><span class="line">UsePAM no　　               # CentOS 7.5 中需要修改为 yes</span><br><span class="line"></span><br><span class="line">#下面参数选项根据自身需要进行修改；</span><br><span class="line">PasswordAuthentication yes　#允许密码认证登录(不要手贱设置为 no, 不然你就登不上服务器了)</span><br><span class="line">PermitRootLogin no　　　　　　#允许root认证登录</span><br></pre></td></tr></table></figure><ol start="2"><li>添加密钥</li></ol><p>将客户端id_rsa.pub文件内容复制到服务端authorized_keys文件</p><ol start="3"><li>重启服务</li></ol><p>重启sshd服务<code>system restart sshd</code></p><ol start="4"><li>登录成功</li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">~ ssh 91-p</span><br><span class="line">Last login: Fri Nov 29 10:16:33 2019 from 172.16.18.131</span><br><span class="line">[root@localhost ~]#</span><br></pre></td></tr></table></figure><h4 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h4><ul><li>查看安全登录日志</li></ul><p><code>cat /var/log/secure</code></p><ul><li>权限问题</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">chmod 700 ~/.ssh</span><br><span class="line">chmod 644 ~/.ssh/authorized_keys  # 信任文件的权限，必须是644</span><br><span class="line">chmod 600 ~/.ssh/id_rsa　　　　　# 私钥文件的权限</span><br></pre></td></tr></table></figure><ul><li>服务器配置问题</li></ul><p><code>getenforce</code> setenforce 0把SELinux关闭</p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;生成密钥&quot;&gt;&lt;a href=&quot;#生成密钥&quot; class=&quot;headerlink&quot; title=&quot;生成密钥&quot;&gt;&lt;/a&gt;生成密钥&lt;/h4&gt;
      
    
    </summary>
    
    
      <category term="Linux" scheme="https://liushuai97.github.io/categories/Linux/"/>
    
    
      <category term="Linux" scheme="https://liushuai97.github.io/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript-自测题20</title>
    <link href="https://liushuai97.github.io/2019/11/28/JavaScript-%E8%87%AA%E6%B5%8B%E9%A2%9820/"/>
    <id>https://liushuai97.github.io/2019/11/28/JavaScript-自测题20/</id>
    <published>2019-11-28T07:18:17.000Z</published>
    <updated>2019-11-28T08:51:28.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">var s = [];</span><br><span class="line">var arr = s;</span><br><span class="line">for(var i = 0; i &lt; 3; i++)&#123;</span><br><span class="line">  var pusher = &#123;</span><br><span class="line">    value: &quot;item&quot; + i</span><br><span class="line">  &#125;,tmp;</span><br><span class="line"></span><br><span class="line">  // i = 0 </span><br><span class="line">  // pusher = &#123;value: &quot;item0&quot;&#125;</span><br><span class="line">  // tmp.children = &#123;value: &quot;item0&quot;&#125;</span><br><span class="line">  // arr = &#123;value: &quot;item0&quot;&#125;</span><br><span class="line">  // s[0] = &#123;value: &quot;item0&quot;,children:[&#123;value:&quot;item0&quot;&#125;]&#125;</span><br><span class="line"></span><br><span class="line">  if(i !== 2)&#123;</span><br><span class="line">    tmp = [];</span><br><span class="line">    pusher.children = tmp;</span><br><span class="line">  &#125;</span><br><span class="line">  arr.push(pusher);</span><br><span class="line">  arr = tmp;</span><br><span class="line">&#125;</span><br><span class="line">console.log(s[0]);</span><br><span class="line"></span><br><span class="line">技术点：指针移动</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span cl
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/categories/JavaScript/"/>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript-自测题19</title>
    <link href="https://liushuai97.github.io/2019/11/28/JavaScript-%E8%87%AA%E6%B5%8B%E9%A2%9819/"/>
    <id>https://liushuai97.github.io/2019/11/28/JavaScript-自测题19/</id>
    <published>2019-11-28T07:18:11.000Z</published>
    <updated>2019-11-28T08:14:12.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="什么是Promise"><a href="#什么是Promise" class="headerlink" title="什么是Promise"></a>什么是Promise</h4><p>Promise是抽象异步处理对象以及对其进行各种操作的组件，其实Promise就是一个对象，用来传递异步操作的消息，它不是某门语言特有的属性，ES6 将其写进了语言标准，统一了用法，原生提供了Promise对象，Promise对象有以下两个特点:</p><ol><li><p>对象的状态不受外界影响</p></li><li><p>一旦状态改变，就不会再变，任何时候都可以得到这个结果</p></li></ol><p>Promise也以下缺点:</p><ol><li><p>无法取消Promise，一旦新建它就会立即执行，无法中途取消。</p></li><li><p>如果不设置回调函数，Promise内部抛出的错误，不会反应到外部。</p></li><li><p>当处于Pending状态时，无法得知目前进展到哪一个阶段（刚刚开始还是即将完成）。</p></li></ol><h4 id="Promise-A-规范的Promise"><a href="#Promise-A-规范的Promise" class="headerlink" title="Promise/A+规范的Promise"></a>Promise/A+规范的Promise</h4><p>Promise/A+是Promise的一个主流规范，浏览器,node和JS库依据此规范来实现相应的功能，以此规范来实现一个Promise也可以叫做实现一个Promise/A+。</p><ul><li><p>类和构造器的构建</p></li><li><p>Promise.prototype.then链式支持</p></li><li><p>静态方法Promise.resolve</p></li><li><p>静态方法Promise.reject</p></li><li><p>静态方法Promise.all</p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">/**</span><br><span class="line">* all方法，可以传入多个promise，全部执行完后会将结果以数组的方式返回，如果有一个失败就返回失败</span><br><span class="line">* 静态方法为类自己的方法，不在原型链上</span><br><span class="line">*/</span><br></pre></td></tr></table></figure><ul><li>静态方法Promise.race</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">事务</span><br><span class="line">/**</span><br><span class="line">* race方法，可以传入多个promise，返回的是第一个执行完的resolve的结果，如果有一个失败就返回失败</span><br><span class="line">*  静态方法为类自己的方法，不在原型链上</span><br><span class="line">*/</span><br></pre></td></tr></table></figure><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">const pro = new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">  const innerpro = new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">    setTimeout(() =&gt; &#123;</span><br><span class="line">      resolve(1);</span><br><span class="line">    &#125;)</span><br><span class="line">    console.log(2);</span><br><span class="line">    resolve(3);</span><br><span class="line">  &#125;)</span><br><span class="line">  innerpro.then(res =&gt; console.log(res));</span><br><span class="line">  resolve(4);</span><br><span class="line">  console.log(&quot;yideng&quot;);</span><br><span class="line">&#125;)</span><br><span class="line">pro.then(res =&gt; console.log(res));</span><br><span class="line">console.log(&quot;end&quot;);</span><br><span class="line"></span><br><span class="line">解析：</span><br><span class="line"></span><br><span class="line">优先执行内部嵌套的new Promise，console.log(2)  然后执行console.log(&quot;yideng&quot;)</span><br><span class="line">pro.then等待</span><br><span class="line">先执行console.log(&quot;end&quot;)</span><br><span class="line">然后执行嵌套内部的resolve(3)</span><br><span class="line">在执行外部的resolve(4)</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;什么是Promise&quot;&gt;&lt;a href=&quot;#什么是Promise&quot; class=&quot;headerlink&quot; title=&quot;什么是Prom
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/categories/JavaScript/"/>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript-自测题18</title>
    <link href="https://liushuai97.github.io/2019/11/28/JavaScript-%E8%87%AA%E6%B5%8B%E9%A2%9818/"/>
    <id>https://liushuai97.github.io/2019/11/28/JavaScript-自测题18/</id>
    <published>2019-11-28T06:55:43.000Z</published>
    <updated>2019-11-28T07:17:48.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">请问点击&lt;button id=&quot;test&quot;&gt;&lt;/button&gt;会有什么反应？为什么？能解决吗？</span><br><span class="line"></span><br><span class="line">$(&quot;#test&quot;).click(function(argument)&#123;</span><br><span class="line">  console.log(1); 控制台打印1</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">setTimeout(function()&#123;</span><br><span class="line">  console.log(2); // 2 立即执行控制台打印2</span><br><span class="line">&#125;,0);</span><br><span class="line"></span><br><span class="line">while(true)&#123;</span><br><span class="line">  console.log(Math.random()); //返回随机数</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">解析：</span><br><span class="line">优先执行while 无限循环  后面无法执行</span><br><span class="line"></span><br><span class="line">技术点：在JS单线程的时候如何模拟多线程操作</span><br><span class="line"></span><br><span class="line">解决：</span><br><span class="line">1. 让出CPU时间，setTimeout延迟执行</span><br><span class="line">2. web worker 独立线程开放（无法执行DOM操作，只允许纯计算）</span><br><span class="line">3. 并发库Concurrent.Thread.js  实现原理时间切片</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span cl
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/categories/JavaScript/"/>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript-自测题17</title>
    <link href="https://liushuai97.github.io/2019/11/27/JavaScript-%E8%87%AA%E6%B5%8B%E9%A2%9817/"/>
    <id>https://liushuai97.github.io/2019/11/27/JavaScript-自测题17/</id>
    <published>2019-11-27T08:05:21.000Z</published>
    <updated>2019-11-28T06:58:40.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><p>请解释babel编译后的async原理</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">let a = 0;</span><br><span class="line">let yideng = async () =&gt; &#123;</span><br><span class="line">  a = a + await 10;</span><br><span class="line">  console.log(a) // 10</span><br><span class="line">&#125;</span><br><span class="line">yideng();</span><br><span class="line">console.log(++a); // 1</span><br></pre></td></tr></table></figure><h4 id="async-await"><a href="#async-await" class="headerlink" title="async/await"></a>async/await</h4><p>在async/await之前，我们有三种方式写异步代码：</p><ol><li><p>嵌套回调</p></li><li><p>以Promise为主的链式回调</p></li><li><p>使用Generators</p></li></ol><h4 id="async特点"><a href="#async特点" class="headerlink" title="async特点"></a>async特点</h4><ol><li><p>async/await更加语义化，async 是“异步”的简写，async function 用于申明一个 function 是异步的；await，可以认为是async wait的简写， 用于等待一个异步方法执行完成；</p></li><li><p>async/await是一个用同步思维解决异步问题的方案（等结果出来之后，代码才会继续往下执行）</p></li><li><p>可以通过多层async function的同步写法代替传统的callback嵌套</p></li></ol><h4 id="async-function语法"><a href="#async-function语法" class="headerlink" title="async function语法"></a>async function语法</h4><ul><li><p>自动将常规函数转换成Promise，返回值也是一个Promise对象</p></li><li><p>只有async函数内部的异步操作执行完，才会执行then方法指定的回调函数</p></li><li><p>异步函数内部可以使用await</p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">async function name([param[, param[, ... param]]]) &#123; statements &#125;</span><br><span class="line">name: 函数名称。</span><br><span class="line">param:  要传递给函数的参数的名称</span><br><span class="line">statements: 函数体语句。</span><br><span class="line">返回值: 返回的Promise对象会以async function的返回值进行解析，或者以该函数抛出的异常进行回绝。</span><br></pre></td></tr></table></figure><h4 id="await语法"><a href="#await语法" class="headerlink" title="await语法"></a>await语法</h4><ul><li><p>await放置在Promise调用之前，await强制后面点代码等待，知道Promise对象resolve，得到resolve的值作为await表达式的运算结果</p></li><li><p>await只能在async函数内部使用，用在普通函数里就会报错</p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[return_value] = await expression;</span><br><span class="line">expression:  一个 Promise  对象或者任何要等待的值。</span><br><span class="line">返回值:返回 Promise 对象的处理结果。如果等待的不是 Promise 对象，则返回该值本身。</span><br></pre></td></tr></table></figure><h4 id="错误处理"><a href="#错误处理" class="headerlink" title="错误处理"></a>错误处理</h4><p>在async函数里，无论是Promise reject的数据还是逻辑报错，都会被默默吞掉,所以最好把await放入try{}catch{}中，catch能够捕捉到Promise对象rejected的数据或者抛出的异常。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">function timeout(ms) &#123;</span><br><span class="line">  return new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">    setTimeout(() =&gt; &#123;reject(&apos;error&apos;)&#125;, ms);  //reject模拟出错，返回error</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">async function asyncPrint(ms) &#123;</span><br><span class="line">  try &#123;</span><br><span class="line">    console.log(&apos;start&apos;);</span><br><span class="line">    await timeout(ms);  //这里返回了错</span><br><span class="line">    console.log(&apos;end&apos;);  //所以这句代码不会被执行了</span><br><span class="line">  &#125; catch(err) &#123;</span><br><span class="line">    console.log(err); //这里捕捉到错误error</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line">asyncPrint(1000);</span><br></pre></td></tr></table></figure><p>如果不用try/catch的话，也可以像下面这样处理错误（因为async函数执行后返回一个promise）</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">function timeout(ms) &#123;</span><br><span class="line">  return new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">    setTimeout(() =&gt; &#123;reject(&apos;error&apos;)&#125;, ms);  //reject模拟出错，返回error</span><br><span class="line">  &#125;);</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">async function asyncPrint(ms) &#123;</span><br><span class="line">  console.log(&apos;start&apos;);</span><br><span class="line">  await timeout(ms)</span><br><span class="line">  console.log(&apos;end&apos;);  //这句代码不会被执行了</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">asyncPrint(1000).catch(err =&gt; &#123;</span><br><span class="line">  console.log(err)； // 从这里捕捉到错误</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><h4 id="使用场景"><a href="#使用场景" class="headerlink" title="使用场景"></a>使用场景</h4><p>多个await命令的异步操作，如果不存在依赖关系（后面的await不依赖前一个await返回的结果），用Promise.all()让它们同时触发</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br></pre></td><td class="code"><pre><span class="line">function test1 () &#123;</span><br><span class="line">    return new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">        setTimeout(() =&gt; &#123;</span><br><span class="line">            resolve(1)</span><br><span class="line">        &#125;, 1000)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">function test2 () &#123;</span><br><span class="line">    return new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">        setTimeout(() =&gt; &#123;</span><br><span class="line">            resolve(2)</span><br><span class="line">        &#125;, 2000)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">async function exc1 () &#123;</span><br><span class="line">    console.log(&apos;exc1 start:&apos;,Date.now())</span><br><span class="line">    let res1 = await test1();</span><br><span class="line">    let res2 = await test2(); // 不依赖 res1 的值</span><br><span class="line">    console.log(&apos;exc1 end:&apos;, Date.now())</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">async function exc2 () &#123;</span><br><span class="line">    console.log(&apos;exc2 start:&apos;,Date.now())</span><br><span class="line">    let [res1, res2] = await Promise.all([test1(), test2()])</span><br><span class="line">    console.log(&apos;exc2 end:&apos;, Date.now())</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">exc1();</span><br><span class="line">exc2();</span><br></pre></td></tr></table></figure><h4 id="例题："><a href="#例题：" class="headerlink" title="例题："></a>例题：</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">async function async1()&#123;</span><br><span class="line">  console.log(1)   // 1</span><br><span class="line">  await async2();</span><br><span class="line">  console.log(3)  // 3</span><br><span class="line">&#125;</span><br><span class="line">async function async2()&#123;</span><br><span class="line">  console.log(2)</span><br><span class="line">&#125;</span><br><span class="line">async1(); // 2</span><br><span class="line">console.log(4)   // 4</span><br><span class="line"></span><br><span class="line">解析：</span><br><span class="line"></span><br><span class="line">优先执行 console.log(1);</span><br><span class="line">await async2() 执行函数 存在立即执行内容 console.log(2)</span><br><span class="line">强制等待...</span><br><span class="line">执行console.log(4)</span><br><span class="line">继续执行console.log(3)</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;请解释babel编译后的async原理&lt;/p&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td cl
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/categories/JavaScript/"/>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>Nodejs项目架构和优化</title>
    <link href="https://liushuai97.github.io/2019/11/27/Nodejs%E9%A1%B9%E7%9B%AE%E6%9E%B6%E6%9E%84%E5%92%8C%E4%BC%98%E5%8C%96/"/>
    <id>https://liushuai97.github.io/2019/11/27/Nodejs项目架构和优化/</id>
    <published>2019-11-27T07:40:37.000Z</published>
    <updated>2019-11-30T02:14:06.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="Nodejs应用场景"><a href="#Nodejs应用场景" class="headerlink" title="Nodejs应用场景"></a>Nodejs应用场景</h4><ol><li>Web开发：Express + EJS + Mongoose/MySQL</li><li>REST开发：Restify</li><li>Web聊天室(IM)：Express + Socket.io</li><li>Web爬虫：Cheerio/Request</li><li>Web博客：Hexo</li><li>Web论坛: nodeclub</li><li>Web幻灯片：Cleaver</li><li>前端包管理平台: bower.js</li><li>Auth认证：Passport</li><li>定时任务工具: later</li><li>浏览器环境工具: browserify</li><li>命令行编程工具：Commander</li><li>Web控制台工具: tty.js</li><li>客户端应用工具: node-webkit</li><li>操作系统: node-os</li></ol><h4 id="Node架构和优化"><a href="#Node架构和优化" class="headerlink" title="Node架构和优化"></a>Node架构和优化</h4><ol><li>NodeJS异步优化IO原理浅析及优化方案</li></ol><ul><li>异步IO的是与非</li></ul><p>前端通过异步IO（input输入/output输出）可以消除UI堵塞<br>NodeJs适用于IO密集型不适用CPU密集型</p><ul><li>Node对异步IO的实现</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">var fs = require(&apos;fs&apos;);</span><br><span class="line"></span><br><span class="line">fs.readFile(&apos;/path1&apos;, function (err, file) &#123; </span><br><span class="line">  console.log(&apos;读取文件1完成&apos;);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line">fs.readFile(&apos;/path2&apos;, function (err, file) &#123;</span><br><span class="line">  console.log(&apos;读取文件2完成&apos;); </span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>完美的异步IO应该是应用程序发起非阻塞调用，无需通过遍历或者事件幻想等方式轮询。</p><ul><li>几个特殊的API</li></ul><p>SetTimeout和Setinterval线程池不参与</p><p>process.nextTick()实现蕾西SetTimeout(function(){},0)，每次调用放入队列中，在下一轮循环中取出。</p><p>setImmediate()比process.nextTick()优先级低</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">setImmediate(function()&#123;</span><br><span class="line">  console.log(2)</span><br><span class="line">&#125;)</span><br><span class="line">setTimeout(function()&#123;</span><br><span class="line">  console.log(1)</span><br><span class="line">&#125;,0)</span><br><span class="line">new Promise((resovle,reject)=&gt;&#123;</span><br><span class="line">  console.log(4)</span><br><span class="line">  resovle(4)</span><br><span class="line">&#125;).then(function()&#123;</span><br><span class="line">  console.log(5)</span><br><span class="line">&#125;)</span><br><span class="line">process.nextTick(()=&gt;&#123;</span><br><span class="line">  console.log(3)</span><br><span class="line">&#125;)</span><br><span class="line">console.log(6)</span><br><span class="line"></span><br><span class="line">// 4 6 3 5 1 2</span><br><span class="line">// sync &gt; micro(tick &gt; promise) &gt; macro(timeout, immediate)</span><br></pre></td></tr></table></figure><p>Node如何实现一个Sleep(休眠)?</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br></pre></td><td class="code"><pre><span class="line">function sleep1(ms, callback) &#123;</span><br><span class="line">    setTimeout(callback, ms)</span><br><span class="line">&#125;</span><br><span class="line">//sleep 1s</span><br><span class="line">sleep1(1000, () = &gt;&#123;</span><br><span class="line">    console.log(1000)</span><br><span class="line">&#125;)</span><br><span class="line">//方法二</span><br><span class="line">function sleep2(ms) &#123;</span><br><span class="line">    return new Promise(function(resolve, reject) &#123;</span><br><span class="line">        setTimeout(resolve, ms)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">sleep2(1000).then(() = &gt;&#123;</span><br><span class="line">    console.log(2000)</span><br><span class="line">&#125;)</span><br><span class="line">//方法三</span><br><span class="line">function sleep3(ms) &#123;</span><br><span class="line">    return new Promise(function(resolve, reject) &#123;</span><br><span class="line">        setTimeout(resolve, ms)</span><br><span class="line">    &#125;)</span><br><span class="line">&#125;</span><br><span class="line">async</span><br><span class="line">function init() &#123;</span><br><span class="line">    await sleep3(1000);</span><br><span class="line">&#125;</span><br><span class="line">init().then(() = &gt;&#123;</span><br><span class="line">    console.log(3000)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure><ul><li>函数式编程在Node中的应用</li><li>常用的Node控制异步API的技术手段</li></ul><ol start="2"><li>NdoeJS内存管理机制及内存优化</li></ol><ul><li><p>V8垃圾回收机制</p></li><li><p>新生代内存、老生代内存</p></li><li><p>内存监控</p></li><li><p>内存泄漏分析（内存快照）</p></li><li><p>性能监控</p></li></ul><p>dynatrace<br>monitr<br>easy-monitor<br>CPU占用率，内存数</p><ul><li>异常处理</li></ul><p>try catch的方式捕获业务异常<br>全局捕获异常<br>koa中间件捕获</p><ol start="3"><li>大规模Node站点解构原理分析</li></ol><ul><li>Nginx</li><li>PM2</li></ul><ol start="4"><li><p>服务器集群管理与Node集群的应用</p></li><li><p>ServerLess/FAAS</p></li></ol><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;Nodejs应用场景&quot;&gt;&lt;a href=&quot;#Nodejs应用场景&quot; class=&quot;headerlink&quot; title=&quot;Nodejs应
      
    
    </summary>
    
    
      <category term="Nodejs" scheme="https://liushuai97.github.io/categories/Nodejs/"/>
    
    
      <category term="Nodejs" scheme="https://liushuai97.github.io/tags/Nodejs/"/>
    
  </entry>
  
  <entry>
    <title>HTTP协议（下）</title>
    <link href="https://liushuai97.github.io/2019/11/27/HTTP%E5%8D%8F%E8%AE%AE%EF%BC%88%E4%B8%8B%EF%BC%89/"/>
    <id>https://liushuai97.github.io/2019/11/27/HTTP协议（下）/</id>
    <published>2019-11-27T02:14:51.000Z</published>
    <updated>2019-11-27T07:33:44.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="密码学入门"><a href="#密码学入门" class="headerlink" title="密码学入门"></a>密码学入门</h4><p>密码学的处理对象是数字和字符串。</p><p>散列是一种数据一旦转换为其他形式将永远无法恢复的加密技术，例如：MD5</p><p>加密：</p><ul><li>对称加密（AES、DES、3DES）</li><li>非对称加密（RSA）</li></ul><p>密钥交换算法</p><p>Diffie-Hellman算法是一种注明的密钥协商算法，这种算法可以使得信息交换的双方通过公开的非安全的网络协商生成安全的共享密钥</p><ul><li>Alice与Bob确定两个大素数n和g，这两个数不用保密</li><li>Alice选择另一个大随机数x，并计算A如下：A=gx mod n</li><li>Alice将A发给Bob</li><li>Bob选择另一个大随机数y，并计算B如下：B=gy mod n</li><li>Bob将B发给Alice</li><li>计算秘密密钥K1如下：K1= Bx mod n</li><li>计算秘密密钥K2如下：K2= Ag mod n</li></ul><p>K1-K2，因此Alice和Bob可以用其进行加解密</p><h4 id="证书签发机构（CA）"><a href="#证书签发机构（CA）" class="headerlink" title="证书签发机构（CA）"></a>证书签发机构（CA）</h4><p>CA： CA（certification authority）是数字证书的签发机构，作为权威机构哦，其审核申请者身份后签发数字证书，这样我们只需要效验数字证书即可确定对方的真实身份。</p><p>CA的工作流程：</p><ul><li>服务器example.com将CA请求TLS证书，例如DigiCer</li><li>DigiCert将为example.com创建证书，证书将包含必要的数据，例如服务器名称，服务器的公钥等。</li><li>DigiCert将创建数据（证书）的哈希值，并使用自己的私钥对其进行加密。</li><li>浏览器和操作系统自带DigiCert等权威机构的公钥</li><li>当浏览器收到签名证书时，它将使用公钥从签名生成哈希值，它还将使用证书中指定的散列算法生成数据（证书）的散列。如果两个哈希值匹配，则签名验证成功并且证书是可信的。</li><li>现在浏览器可以使用证书中指定的example.com的公钥继续进行身份验证过程。</li><li>在这里，我们可以将DigiCert称为Root CA</li></ul><h4 id="浏览器如何验证服务器证书的有效性"><a href="#浏览器如何验证服务器证书的有效性" class="headerlink" title="浏览器如何验证服务器证书的有效性"></a>浏览器如何验证服务器证书的有效性</h4><p>证书颁发机构是为服务器创建并签署证书，很少有组织从事这项工作，即DigiCert、Geotrust、Comodo等。如果他们正在为所有服务器签署证书，则必须为所有签名使用相同的私钥，如果它被盗，那么所有的信任都会丢失。为了解决这个问题并增加更多的平均信息量，引入了中间(CAintermediate CA)的概念。</p><p>服务器使用中级证书颁发机构的签名，因此，在于浏览器通信时，服务器将共享两个证书：</p><ol><li>包含服务器的公钥，即实际的服务器证书；</li><li>由Root CA颁发的intermediate CA证书。</li></ol><p>在签名验证期间，浏览器首先使用已经存储在浏览器中的Root CA 的公钥来验证中检证书的数字签名，如果成功，浏览器现在可以信任中间证书及其公钥。现在使用此公钥、浏览器将验证原始服务器证书的签名，该组织可以注册为intermediate CA，以便为其域签署证书。</p><h4 id="SSL-TLS协议"><a href="#SSL-TLS协议" class="headerlink" title="SSL/TLS协议"></a>SSL/TLS协议</h4><p>传输层安全性协议（TLS），及其前身安全套阶层(SSl)是一种安全协议，目的是为互联网通信提供安全及数据完整性保障。</p><p>HTTPS协议的安全性由SSL协议实现，当前使用的TLS协议1.2版本包含了四个核心子协议：握手协议、密钥配置切换协议、应用数据协议及报警协议.</p><ul><li>TLS适用于对称密钥</li><li>对称密钥可以通过安全密钥交换算法共享</li><li>如果请求被截获，密钥交换可能会被欺骗</li><li>使用数字签名进行身份验证</li><li>证书颁发机构和信任链</li></ul><p>HTTPS协议、SSL协议、TLS协议、握手协议的关系</p><ul><li>HTTPS即HTTP over SSL，可理解为基于SSL的HTTP协议。HTTPS协议安全是由SSL协议实现的。</li><li>SSL协议是一种记录协议，扩展性良好，可以很方便的添加子协议。</li><li>握手协议是SSL协议的一个子协议</li><li>TLS协议是SSL协议的后续版本</li></ul><h4 id="HTTPS协议分析"><a href="#HTTPS协议分析" class="headerlink" title="HTTPS协议分析"></a>HTTPS协议分析</h4><p>TLS握手的步骤</p><p><img src="TLS.jpeg" alt="kyrie irving"></p><p>HTTPS的协议本质上就是在HTTP协议连接发起之前，先使用SSL/TLS协议，协调客户端和服务器端，在两端各自产生一个堆成加密算法的秘钥，然后以RSA（对之前生成的秘钥进行非对称加密）的方式安全地传输数据。因为对称加密算法是安全的，所以使用对称加密算法加密的网页也是安全的。</p><p>HTTPS</p><p>非对称加密算法(对称加密算法的秘钥，RSA) + 对称加密算法(加密内容，DES) + 数字证书(防止篡改非对称加密算法的公钥，CA) + HASH算法(防止篡改消息，MD5/SHA1)</p><p>HTTPS 结合使用了 非对称加密算法，对称加密算法，hash算法，分别利用他们的优势，避免他们的缺点。</p><p>利用非对称加密算法获得对称加密算法的秘钥，保证他的安全性；然后实际的网页内容的加密使用的是对称加密算法，利用了对称加密算法速度快的优势，hash算法主要是防止篡改的发生，是一种校验机制，最后数字证书，保证了服务器在将非对称加密算法的公钥传给浏览器时的安全性(不会被中间人篡改)，同时也标志了服务器的身份。</p><h4 id="HTTP2协议分析"><a href="#HTTP2协议分析" class="headerlink" title="HTTP2协议分析"></a>HTTP2协议分析</h4><p>HTTP/2没有改动HTTP的应用语义。HTTP方法、状态代码、URI和标头字段等核心概念一如往常。</p><p>HTTP/2修改数据格式化（分帧）以及在客户端与服务器间传输的方式。这两点统帅全局，通过新的分帧层向我们应用隐藏了所有复杂性。</p><p>由于HTTP/2引入了一个新的二进制分帧层，该层无法与之前的HTTP/1.x服务器和客户端向后兼容，因此协议的主版本提升到HTTP/2。</p><p>HTTP2的特点：</p><ul><li><p>使用二进制格式传输、更高效、更紧凑</p></li><li><p>对报头压缩、降低开销</p></li><li><p>多路复用、一个网络连接实现并行请求。</p></li><li><p>服务器主动推送，减少请求的延迟</p></li><li><p>默认使用加密</p></li></ul><h4 id="HTTP2-二进制分帧"><a href="#HTTP2-二进制分帧" class="headerlink" title="HTTP2 二进制分帧"></a>HTTP2 二进制分帧</h4><p>HTTP/2所有性能增强的核心在于新的二进制分帧层，它定义了如何封装HTTP消息并在客户端与服务器端之间传输。</p><p>这里所谓的“层”指的是为套接字接口与应用可见的高级HTTP API之间一个经过优化的新编码机制。</p><p>HTTP/1.x协议以换行符作为纯文本的分隔符，而HTTP/2将所有传输的信息风格为更小的消息和帧，并采用二进制格式对他们编码。</p><p>客户端和服务器会替我们完成必要的分帧工作。</p><h4 id="HTTP2-多路复用"><a href="#HTTP2-多路复用" class="headerlink" title="HTTP2 多路复用"></a>HTTP2 多路复用</h4><p>在HTTP/1.x中，如果客户端想法器多个并行请求以提升性能，则必须使用多个TCP连接。这种模型也会导致队首阻塞，从而造成底层TCP连接的效率低下。</p><p>将HTTP消息分解为独立的帧，交错发送，然后再另一端重新组装是HTTP2最重要的一项增强，这个机制会在整个网络技术栈中引发一系列连锁反应，而从带来巨大的性能提升。</p><ul><li>并行交错地发送多个请求，请求之间互不影响。</li><li>并行交错地发送多个响应，响应之间互不干扰</li><li>使用一个连接并行发送多个请求和响应。</li><li>不必再为绕过HTTP/1.x限制而做更多工作。</li><li>消除不必要的延迟和提高现有网络容量的利用率，从而减少页面加载时间。</li></ul><h4 id="HTTP2-服务器推送"><a href="#HTTP2-服务器推送" class="headerlink" title="HTTP2 服务器推送"></a>HTTP2 服务器推送</h4><p>HTTP/2新增的另一个强大的新功能，是服务器可以对一个客户端请求发送多个响应，换句话说，除了对最初请求的响应外，服务器还可以向客户端推送额外资源，而无需客户明确地请求。</p><p>HTTP/2打破了严格的请求-响应语义，支持一对多和服务器发起的推送工作流。</p><p>服务器已经知道客户端下一步要请求什么资源，这时候服务器推送即可派上用场。</p><p>推送资源可以进行以下处理：</p><ul><li>由客户端缓存</li><li>在不同页面之间重用</li><li>与其他资源一起复用</li><li>由服务器设定优先级</li><li>被客户端拒绝</li></ul><h4 id="HTTP2的伪头字段"><a href="#HTTP2的伪头字段" class="headerlink" title="HTTP2的伪头字段"></a>HTTP2的伪头字段</h4><p>伪头部字段是HTTP2内置的几个特殊的以“:”开始的key，用于替换HTTP/1.x中请求行/响应行中的信息，比如请求方法，响应状态码等</p><p>:method 目标URL模式部分（请求）<br>:scheme 目标URL模式部分（请求）<br>:authority 目标URL认证部分（请求）<br>:path 目标URL的路径和查询部分（绝对路径产生式和一个跟着“?”字符的查询产生式）（请求）<br>:status 响应头中的HTTP状态码部分（响应）</p><h4 id="了解HTTP3"><a href="#了解HTTP3" class="headerlink" title="了解HTTP3"></a>了解HTTP3</h4><p>运行在QUIC智商的HTTP协议被称为HTTP/3 （HTTP-over-QUIC）</p><p>QUIC协议基于UDP，正式看中了UDP的速度和效率，同事QUIC业整合了TCP、TLS和HTTP/2的有点，并加以优化。</p><p>特点：</p><ul><li>减少了握手的延迟（1-RTT或0-RTT）</li><li>多路复用、并且没有TCP的阻塞问题</li><li>连接迁移、（主要是客户端）当由wifi转移到4G时，连接不会断开。</li></ul><p>HTTP3与HTTP1.1和HTTP2没有直接关系，也不是HTTP2的扩展</p><p>HTTP3将会是一个全新的WEB协议</p><p>HTTP3目前处于制订和测试阶段</p><h4 id="对首阻塞问题"><a href="#对首阻塞问题" class="headerlink" title="对首阻塞问题"></a>对首阻塞问题</h4><p>HTTP/1.1和HTTP/2都存在对头阻塞问题</p><p>HTTP/2必须使用HTTPS，而HTTPS使用的TLS协议也存在对首阻塞问题。</p><p>QUIC解决队首阻塞问题的方法：</p><ul><li>QUIC的传输单元式Packet，加密单元也是Packet，整个加密、传输、解密都基于Packet，这样就能避免TLS的队首阻塞问题</li><li>QUIC基于UDP，UDP的数据包在接收端没有处理顺序，及时中间丢失一个包，也不会阻塞整条连接，其他资源会被正常处理。</li></ul><h4 id="HTTP与反向代理"><a href="#HTTP与反向代理" class="headerlink" title="HTTP与反向代理"></a>HTTP与反向代理</h4><p>反向代理的用途</p><ul><li>加密和SSL加速</li><li>负载均衡</li><li>缓存静态内容</li><li>压缩</li><li>减速上传</li><li>安全</li><li>外网发布</li></ul><p>Nginx: <a href="http://shouce.jb51.net/nginx/left.html" target="_blank" rel="noopener">http://shouce.jb51.net/nginx/left.html</a></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;密码学入门&quot;&gt;&lt;a href=&quot;#密码学入门&quot; class=&quot;headerlink&quot; title=&quot;密码学入门&quot;&gt;&lt;/a&gt;密码学入门&lt;
      
    
    </summary>
    
    
      <category term="HTTP" scheme="https://liushuai97.github.io/categories/HTTP/"/>
    
    
      <category term="HTTP" scheme="https://liushuai97.github.io/tags/HTTP/"/>
    
  </entry>
  
  <entry>
    <title>HTTP协议（上）</title>
    <link href="https://liushuai97.github.io/2019/11/26/HTTP%E5%8D%8F%E8%AE%AE%EF%BC%88%E4%B8%8A%EF%BC%89/"/>
    <id>https://liushuai97.github.io/2019/11/26/HTTP协议（上）/</id>
    <published>2019-11-26T00:44:46.000Z</published>
    <updated>2019-11-26T06:22:32.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="HTTP请求模型"><a href="#HTTP请求模型" class="headerlink" title="HTTP请求模型"></a>HTTP请求模型</h4><ol><li>两端：客户端（Client）、服务端（Server）</li><li>服务器响应</li><li>客户端请求</li></ol><p>浏览器行为与HTTP协议：</p><ol><li>输入网址（判断网络是否连接，是否可以发送互联网请求）</li><li>解析域名（根据域名IP地址查询DNS服务器）</li><li>浏览器发送HTTP请求（传输HTTP数据包）</li><li>服务器处理请求（远端服务器接收HTTP数据包）</li><li>服务器返回HTML响应（接收后响应并返回）</li><li>浏览器处理HTML页面（浏览器渲染）</li><li>继续请求其他资源</li></ol><h4 id="什么是HTTP协议"><a href="#什么是HTTP协议" class="headerlink" title="什么是HTTP协议"></a>什么是HTTP协议</h4><p>HTTP是超文本传输协议，从http服务器传输到本地浏览器的一种传输协议，网站就是基于HTTP协议的，例如网站的图片、CSS、JS等都是基于HTTP协议进行传输的。</p><p>HTTP协议是由客户机到服务器的请求（Request）和从服务器到客户机的响应（response）进行约束和规范。</p><h4 id="了解TCP-IP协议栈"><a href="#了解TCP-IP协议栈" class="headerlink" title="了解TCP/IP协议栈"></a>了解TCP/IP协议栈</h4><ol><li>应用层</li></ol><p>为用户提供所需要的各种服务，例如：HTTP、FTP、DNS、SMTP等</p><ol start="2"><li>传输层</li></ol><p>为应用层实体提供端到端的通信功能，保证数据包的顺序传送及数据的完整性。</p><p>该层定义了两个主要的协议：传输控制协议（TCP）和用户数据报协议（UDP）</p><ol start="3"><li>网络层</li></ol><p>主要解决主机到主机的通信问题，IP协议是网际互联网层最重要的协议</p><ol start="4"><li>网络接口层</li></ol><p>负责监视数据在主机和网络之间的交换</p><h4 id="在TCP-IP协议栈中的位置"><a href="#在TCP-IP协议栈中的位置" class="headerlink" title="在TCP/IP协议栈中的位置"></a>在TCP/IP协议栈中的位置</h4><ol><li><p>目前普遍应用版本HTTP1.1</p></li><li><p>正在逐步向HTTP2迁移</p></li><li><p>HTTP默认端口为80</p></li><li><p>HTTPS默认端口为443</p></li></ol><h4 id="HTTP的工作过程"><a href="#HTTP的工作过程" class="headerlink" title="HTTP的工作过程"></a>HTTP的工作过程</h4><p>一次HTTP操作成为一个事务，其工作过程可分为四步：</p><ol><li><p>首先客户机与服务器需要建立连接，只要单机某个超级链接，HTTP的工作开始</p></li><li><p>建立连接后，客户机发送一个请求给服务器，请求方式的格式为：统一资源标识符（URL）、协议版本号，后边是MIME信息包括请求修饰符、客户及信息和可能的内容。</p></li><li><p>服务器接到请求后，给予相应的响应信息，其格式为一个状态行，包括信息的协议版本、一个成功或错误的代码，后便是MIME信息包括服务器信息，实体信息和可能的内容。</p></li><li><p>客户端接收服务器所返回的信息通过浏览器显示在用户的显示屏上，然后客户机与服务器断开连接。</p></li></ol><p>如果在以上过程中的某一步出现错误，那么产生错误的信息将返回到客户端，有显示屏输出。对于用户来说，这些过程由HTTP自己完成的，用户只要用鼠标点击，等待信息显示就可以了。</p><h4 id="请求和响应"><a href="#请求和响应" class="headerlink" title="请求和响应"></a>请求和响应</h4><p>HTTP请求组成： 请求行、消息报头、请求正文。</p><p>HTTP响应组成： 状态行、消息报头、响应正文。</p><h4 id="请求方法"><a href="#请求方法" class="headerlink" title="请求方法"></a>请求方法</h4><p>GET： 请求获取Request-URI所标识的资源</p><p>POST： 在Request-URI所标识的资源后附加新的数据</p><p>HEAD： 请求获取有Request-URI所标识的资源的响应消息报头</p><p>PUT： 请求服务器存储一个资源，并用Request-URI作为其标识</p><p>DELETE：请求服务器删除Request-URI所标识的资源</p><p>TRACE：请求服务器回送收到的请求信息，主要用于测试或诊断。</p><p>CONNECT：HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。</p><p>OPTIONS：请求查询服务器的性能，或者查询与资源相关的选项和需求</p><h4 id="HTTP状态码"><a href="#HTTP状态码" class="headerlink" title="HTTP状态码"></a>HTTP状态码</h4><p>状态代码有三维数字组成，第一个数字定义了响应的类别，且有五种可能取值：</p><p>1xx：指示信息–标识请求已接收，继续处理</p><p>2xx: 成功–表示请求已被成功接收、理解、接受</p><p>3xx：重定向–要完成请求必须进行更进一步的操作</p><p>4xx：客户端错误–请求有语法错误或请求无法实现</p><p>5xx：服务端错误–服务器未能实现合法的请求</p><h4 id="请求报头域"><a href="#请求报头域" class="headerlink" title="请求报头域"></a>请求报头域</h4><p><img src="Request.png" alt="kyrie irving"></p><h4 id="响应报头域"><a href="#响应报头域" class="headerlink" title="响应报头域"></a>响应报头域</h4><p><img src="response.png" alt="kyrie irving"></p><h4 id="cookies与session"><a href="#cookies与session" class="headerlink" title="cookies与session"></a>cookies与session</h4><p>Cookies是保存在客户端的小段文本，岁客户端点每一个请求发送该URL下的所有cookies到服务器端。</p><p>Session则保存在服务器端，通过唯一的值sessionID来区别每一个用户，SessionID随每个连接请求发送到服务器，服务器根据SessionID来识别客户端，在通过Session的Key获取Session值。</p><h4 id="HTTP缓存机制"><a href="#HTTP缓存机制" class="headerlink" title="HTTP缓存机制"></a>HTTP缓存机制</h4><p>缓存会根据请求保存输出内容的副本，例如HTML页面、图片、文件、当下一个请求来到的时候：若果是相同的URL，缓存直接使用副本响应访问请求，而不是向源服务器再次发送请求。</p><p>缓存的有点：</p><p>减少响应的延迟</p><p>减少网络宽带消耗</p><h4 id="了解缓存策略"><a href="#了解缓存策略" class="headerlink" title="了解缓存策略"></a>了解缓存策略</h4><ol><li><p>强制缓存，服务器通知浏览器一个缓存时间，在缓存时间内，下次请求，直接用缓存，不在时间内，执行比较缓存策略。</p></li><li><p>对比缓存，将缓存信息中的Etag和Last-Modified通过请求发送给服务器，由服务器校验，返回304状态码时，浏览器直接使用缓存。</p></li><li><p>Etag/If-None-Match策略</p></li><li><p>Last-Modified/If-Modified-Since策略</p></li></ol><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;HTTP请求模型&quot;&gt;&lt;a href=&quot;#HTTP请求模型&quot; class=&quot;headerlink&quot; title=&quot;HTTP请求模型&quot;&gt;&lt;
      
    
    </summary>
    
    
      <category term="HTTP" scheme="https://liushuai97.github.io/categories/HTTP/"/>
    
    
      <category term="HTTP" scheme="https://liushuai97.github.io/tags/HTTP/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript&amp;QA工程师</title>
    <link href="https://liushuai97.github.io/2019/11/25/JavaScript-QA%E5%B7%A5%E7%A8%8B%E5%B8%88/"/>
    <id>https://liushuai97.github.io/2019/11/25/JavaScript-QA工程师/</id>
    <published>2019-11-25T00:17:05.000Z</published>
    <updated>2019-11-25T08:49:52.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="测试分层"><a href="#测试分层" class="headerlink" title="测试分层"></a>测试分层</h4><ul><li>单元测试</li></ul><p>单元测试确保基础单元（比如组件、类、函数）没问题</p><ol><li>正确性，保证代码的正确性</li><li>自动化，通过编写测试用例，一次编写，多次运行</li><li>解释性，测试用例用于测试接口、模块的重要性，那么测试用例就会涉及如何使用这些API。</li><li>驱动开发，指导设计，代码被测试的前提是代码本身的可测试性，那么要保证代码的可测试性就要开发中注意API的设计。</li><li>保证重构，互联网行业产品迭代速度很快，迭代后必然存在代码重构的过程，有测试用例做后盾，就可以大胆的进行重构。</li></ol><p>目的：单元测试能够让开发者明确知道代码结果<br>原则：单一职责，接口抽象，层次分离<br>断言库：保证最小单元是否正常运行检测方法<br>测试风格：测试驱动开发（TDD）、行为驱动开发（BDD）是敏捷开发方法论。</p><p>TDD，关注所有功能是否被实现<br>BDD，关注整体行为知否符合整体预期，编写每一行代码都有目的提供一个全面的测试用例集。</p><p>单元测试流程：</p><ol><li>确定测试平台，确定测试平台，代码运行环境等。比如：Node端运行，Chrome运行，推荐Karma</li><li>选择测试框架，mocha，jasmine，jest，ava，辅助的断言库（chai），测试桩（Sinon,testDouble）</li><li>查看测试结果，主要看测试覆盖率。</li></ol><p>单元测试框架：</p><ol><li>better-assert TDD断言库</li><li>should.js BDD断言库</li><li>expect.js BDD断言库</li><li>chai.js TDD、BDD双模</li><li>Jasmine.js BDD断言库</li><li>Node.js 本身继承require(‘assert’)</li><li>Intern 一个大而全的单元测试框架</li><li>QUnit 一个游离在JQuery左右的测试框架</li><li>Macaca 一套完整的自动化测试解决方案</li></ol><ul><li>集成测试</li></ul><p>集成测试确保不同的组件组合在一起没有问题</p><ul><li>自动化测试</li></ul><p>端到端测试是最顶层的测试，即完全作为一个用户一样将程序作为一个完全的黑盒，打开应用程序模式输入，检查功能以及界面是否正确</p><h4 id="其他测试"><a href="#其他测试" class="headerlink" title="其他测试"></a>其他测试</h4><ul><li><p>性能测试</p></li><li><p>基准测试</p></li></ul><ol><li>面向切面变成AOP无侵入式统计</li><li>Benchmark基准测试方法，它并不是简单地统计执行多少次测试代码后对比时间，它对测试有着严密的抽样过程，执行多少次取决于采样到的数据能够完成统计。根据统计次数计算方差。</li></ol><ul><li>压力测试</li></ul><ol><li>对网络接口做压力测试需要检测的介个常用指标有吞吐率、响应时间和并发数，这些指标反映了服务器并发处理能力。</li><li>PV网站当日访问人数UV独立访问人数。PV每天几十万甚至上百万就需要考虑压力测试。换算公式QPS = PV/t</li><li>常用压力测试工具是ab、siege、http_load</li></ol><ul><li>安全测试</li></ul><p>安全漏洞检查</p><ol><li>XSS</li><li>SQL</li><li>CSRF</li><li>敏感路径、敏感词、敏感图片</li></ol><h4 id="代码检测工具ESLint"><a href="#代码检测工具ESLint" class="headerlink" title="代码检测工具ESLint"></a>代码检测工具ESLint</h4><h4 id="常用测试框架"><a href="#常用测试框架" class="headerlink" title="常用测试框架"></a>常用测试框架</h4><ol><li>单元测试 (karma)</li></ol><p>Karma，karma不是一个测试框架，也不是一个断言库。karma只是启动一个HTTP服务器，并生成HTML文件。所以你可以选择你自己喜欢的测试框架。如Jasmine,Mocha,QUnit等等。</p><p>Jasmine，即是上面所说的JavaScript测试框架。它不依赖于其他任何JavaScript组件，它有干净的语法，Jasmine断言库可以让你简单的写出测试代码，（断言：表示为一些布尔表达式，你可以采用假设的方式，当程序输出的结果是否与假设的结果一致时，断言为真，否则，断言为假）在karma上运行Jasmine可以完成JavaScript的自动化测试、生成覆盖率报告等。</p><ol start="2"><li>e2e测试 (selenium-webdriver)</li></ol><p>Selenium已经支持了大部分主流的浏览器，它是一个用于自动化测试的绝佳工具。</p><p>WebDriver（或者Selenium 2）基本上指的都是特定浏览器控制代码的语言绑定和实现。</p><p>WebDriver引入了一个JSON wire protocol用于将不同的语言和浏览器控制器进行交流。</p><ol start="3"><li>UI测试 || “UI走查” (backstopjs)</li></ol><p>BackstopJS就是一个能够实现css自动化回归测试的工具，和Mocha这种依靠JavaScript判断断言语句正误和PhantomJS以模拟用户操作的测试工具不同，BackstopJS是一个基于比较网站快照的变化的回归测试工具，因此他更适给项目中的样式做回归测试，可以确保我们在重构网站样式的时候样式不发生变化，而且他支持设置多种浏览器尺寸，可以测试响应式布局。</p><ol start="4"><li>接口测试 (mocha &amp;&amp; mochawesome)</li></ol><p>mocha是JavaScript的一种单元测试框架，既可以在浏览器环境下运行，也可以在Node.js环境下运行。</p><p>使用mocha，我们就只需要专注于编写单元测试本身，然后，让mocha去自动运行所有的测试，并给出测试结果。</p><p>mocha的特点主要有：</p><ul><li><p>既可以测试简单的JavaScript函数，又可以测试异步代码，因为异步是JavaScript的特性之一；</p></li><li><p>可以自动运行所有测试，也可以只运行特定的测试；</p></li><li><p>可以支持before、after、beforeEach和afterEach来编写初始化代码。</p></li></ul><p>使用mochawesome模块，可以生成漂亮的HTML格式的报告。</p><p>线上地址：<a href="https://github.com/liushuai97/test" target="_blank" rel="noopener">https://github.com/liushuai97/test</a></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;测试分层&quot;&gt;&lt;a href=&quot;#测试分层&quot; class=&quot;headerlink&quot; title=&quot;测试分层&quot;&gt;&lt;/a&gt;测试分层&lt;/h4&gt;
      
    
    </summary>
    
    
      <category term="QA" scheme="https://liushuai97.github.io/categories/QA/"/>
    
    
      <category term="QA" scheme="https://liushuai97.github.io/tags/QA/"/>
    
  </entry>
  
  <entry>
    <title>React数据管理</title>
    <link href="https://liushuai97.github.io/2019/11/22/React%E6%95%B0%E6%8D%AE%E7%AE%A1%E7%90%86/"/>
    <id>https://liushuai97.github.io/2019/11/22/React数据管理/</id>
    <published>2019-11-22T07:19:51.000Z</published>
    <updated>2019-11-22T07:28:32.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="React数据管理"><a href="#React数据管理" class="headerlink" title="React数据管理"></a>React数据管理</h4><ul><li>依靠状态提升来和兄弟元素进行数据交互</li><li>通过发布订阅模式做数据交互</li><li>Redux等数据管理工具</li></ul><h4 id="应用场景"><a href="#应用场景" class="headerlink" title="应用场景"></a>应用场景</h4><ul><li>状态提升：组件层级扁平化，兄弟组件通信情况很少</li></ul><p><img src="state.png" alt="kyrie irving"></p><ul><li>发布订阅模式：业务规模较小，层级较深的业务</li></ul><p><img src="tip.png" alt="kyrie irving"></p><ul><li>Redux：业务复杂，组件层级较深，兄弟组件通信密切</li></ul><p><img src="store.png" alt="kyrie irving"></p><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;React数据管理&quot;&gt;&lt;a href=&quot;#React数据管理&quot; class=&quot;headerlink&quot; title=&quot;React数据管理
      
    
    </summary>
    
    
      <category term="React" scheme="https://liushuai97.github.io/categories/React/"/>
    
    
      <category term="React" scheme="https://liushuai97.github.io/tags/React/"/>
    
  </entry>
  
  <entry>
    <title>React-Router</title>
    <link href="https://liushuai97.github.io/2019/11/22/React-Router/"/>
    <id>https://liushuai97.github.io/2019/11/22/React-Router/</id>
    <published>2019-11-22T00:42:07.000Z</published>
    <updated>2019-11-22T07:11:06.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><p>ReactRouter中提供了以下三大组件：</p><ul><li>路由组件：BrowserRouter（history模式） 和 HashRouter (hash模式)</li><li>路由匹配组件：Route和Switch</li><li>导航组件：Link和NavLink</li></ul><p>当然每个组件下又会有几种不同的子类组件实现。比如： Router组件就针对不同功能和平台对应用：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">&lt;BrowserRouter&gt; 浏览器的路由组件</span><br><span class="line">&lt;HashRouter&gt; URL格式为Hash路由组件</span><br><span class="line">&lt;MemoryRouter&gt; 内存路由组件</span><br><span class="line">&lt;NativeRouter&gt; Native的路由组件</span><br><span class="line">&lt;StaticRouter&gt; 地址不改变的静态路由组件</span><br></pre></td></tr></table></figure><p>注：路由自动跳转，<code>&lt;Redirect&gt;</code></p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br></pre></td><td class="code"><pre><span class="line">import React,&#123;Component&#125; from &apos;react&apos;;</span><br><span class="line">import ReactDOM from &apos;react-dom&apos;</span><br><span class="line">import &#123;</span><br><span class="line">  // HashRouter as Router,</span><br><span class="line">  BrowserRouter as Router,</span><br><span class="line">  Switch,</span><br><span class="line">  Route,</span><br><span class="line">  Link</span><br><span class="line">&#125; from &apos;react-router-dom&apos;</span><br><span class="line"></span><br><span class="line">class A extends React.Component&#123;</span><br><span class="line">  constructor(props)&#123;</span><br><span class="line">    super(props)</span><br><span class="line">  &#125;</span><br><span class="line">  render()&#123;</span><br><span class="line">    return (</span><br><span class="line">      &lt;div&gt;</span><br><span class="line">        Component A</span><br><span class="line">        &lt;br/&gt;</span><br><span class="line">        &#123;/* 参数是：&#123;this.props.match.params.id&#125; */&#125;</span><br><span class="line">        &lt;Switch&gt;</span><br><span class="line">          &lt;Route exact path=&#123;`$&#123;this.props.match.path&#125;`&#125; render=&#123;(route)=&gt;&#123;</span><br><span class="line">            return &lt;div&gt;当前组件是不带参数的A组件&lt;/div&gt;</span><br><span class="line">            &#125;&#125;</span><br><span class="line">          /&gt;</span><br><span class="line">          &lt;Route exact path=&#123;`$&#123;this.props.match.path&#125;/sub`&#125; render=&#123;(route)=&gt;&#123;</span><br><span class="line">            return &lt;div&gt;当前组件是Sub&lt;/div&gt;</span><br><span class="line">            &#125;&#125;</span><br><span class="line">          /&gt;</span><br><span class="line">          &#123;/* 通配一般放置在最后 */&#125;</span><br><span class="line">          &lt;Route path=&#123;`$&#123;this.props.match.path&#125;/:id`&#125; render=&#123;(route)=&gt;&#123;</span><br><span class="line">            return &lt;div&gt;当前组件是带参数的A组件，参数是：&#123;route.match.params.id&#125;&lt;/div&gt;</span><br><span class="line">            &#125;&#125;</span><br><span class="line">          /&gt;</span><br><span class="line">        &lt;/Switch&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">class B extends Component&#123;</span><br><span class="line">  constructor(props)&#123;</span><br><span class="line">    super(props)</span><br><span class="line">  &#125;</span><br><span class="line">  render()&#123;</span><br><span class="line">    return &lt;div&gt;Component B&lt;/div&gt;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">class Wrapper extends Component&#123;</span><br><span class="line">  constructor(props)&#123;</span><br><span class="line">    super(props)</span><br><span class="line">  &#125;</span><br><span class="line">  render()&#123;</span><br><span class="line">    return (</span><br><span class="line">      &lt;div&gt;</span><br><span class="line">        &lt;Link to=&quot;/a&quot;&gt;组件A&lt;/Link&gt;</span><br><span class="line">        &lt;br/&gt;</span><br><span class="line">        &lt;Link to=&quot;/a/123&quot;&gt;带参数组件A&lt;/Link&gt;</span><br><span class="line">        &lt;br/&gt;</span><br><span class="line">        &lt;Link to=&quot;/a/sub&quot;&gt;Sub&lt;/Link&gt;</span><br><span class="line">        &lt;br/&gt;</span><br><span class="line">        &lt;Link to=&quot;/b&quot;&gt;组件B&lt;/Link&gt;</span><br><span class="line">        &#123;this.props.children&#125;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;Router&gt;</span><br><span class="line">    &lt;Wrapper&gt;</span><br><span class="line">    &lt;Route path=&quot;/a&quot; component=&#123;A&#125;/&gt;</span><br><span class="line">    &lt;Route path=&quot;/b&quot; component=&#123;B&#125;/&gt;</span><br><span class="line">  &lt;/Wrapper&gt;</span><br><span class="line">  &lt;/Router&gt;,</span><br><span class="line">  document.getElementById(&apos;app&apos;)</span><br><span class="line">)</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;p&gt;ReactRouter中提供了以下三大组件：&lt;/p&gt;&lt;ul&gt;&lt;li&gt;路由组件：BrowserRouter（history模式） 和 HashRo
      
    
    </summary>
    
    
      <category term="React" scheme="https://liushuai97.github.io/categories/React/"/>
    
    
      <category term="React" scheme="https://liushuai97.github.io/tags/React/"/>
    
  </entry>
  
  <entry>
    <title>路由 Router</title>
    <link href="https://liushuai97.github.io/2019/11/14/%E8%B7%AF%E7%94%B1-Router/"/>
    <id>https://liushuai97.github.io/2019/11/14/路由-Router/</id>
    <published>2019-11-14T07:12:55.000Z</published>
    <updated>2019-11-14T07:15:32.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="Router-原理"><a href="#Router-原理" class="headerlink" title="Router 原理"></a>Router 原理</h4><ul><li>路由历史</li><li>路由跳转</li><li>逻辑事件</li></ul><h4 id="常见Router"><a href="#常见Router" class="headerlink" title="常见Router"></a>常见Router</h4><ul><li>页面Router</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">window.location.href = &apos;http://www.baidu.com&apos;</span><br></pre></td></tr></table></figure><ul><li>Hash Router</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">window.location = &apos;#test&apos;</span><br><span class="line">window.hashchange = function () &#123;</span><br><span class="line">  console.log(&apos;current hash:&apos;, window.location.hash);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>H5路由</li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">推进一个状态：history.pushState(&apos;name&apos;,&apos;title&apos;,&apos;#test&apos;)</span><br><span class="line">history.pushState(&apos;name&apos;,&apos;title&apos;,&apos;/usr/index&apos;)</span><br><span class="line">替换一个状态：history.replaceState(&apos;name&apos;,&apos;title&apos;,&apos;/index/test&apos;)</span><br><span class="line">window.onpopstate = function (e) &#123;</span><br><span class="line">  console.log(&apos;h5 router change&apos;,e.state);</span><br><span class="line">&#125;</span><br><span class="line">window.onpopstate = function () &#123;</span><br><span class="line">  console.log(window.location.href);</span><br><span class="line">  console.log(window.location.pathname);</span><br><span class="line">  console.log(window.location.hash);</span><br><span class="line">  console.log(window.location.search);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;Router-原理&quot;&gt;&lt;a href=&quot;#Router-原理&quot; class=&quot;headerlink&quot; title=&quot;Router 原理
      
    
    </summary>
    
    
      <category term="HTML" scheme="https://liushuai97.github.io/categories/HTML/"/>
    
    
      <category term="HTML" scheme="https://liushuai97.github.io/tags/HTML/"/>
    
  </entry>
  
  <entry>
    <title>React语法</title>
    <link href="https://liushuai97.github.io/2019/11/13/React%E8%AF%AD%E6%B3%95/"/>
    <id>https://liushuai97.github.io/2019/11/13/React语法/</id>
    <published>2019-11-13T09:01:24.000Z</published>
    <updated>2019-11-14T07:15:08.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="JSX语法"><a href="#JSX语法" class="headerlink" title="JSX语法"></a>JSX语法</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line">import React from &apos;react&apos;;</span><br><span class="line">import ReactDOM from &apos;react-dom&apos;;</span><br><span class="line"></span><br><span class="line">import &apos;./index.scss&apos;</span><br><span class="line"></span><br><span class="line">let style = &#123;&#125;;</span><br><span class="line">let name = &apos;Li&apos;;</span><br><span class="line">let names = [&apos;张三&apos;,&apos;李四&apos;,&apos;王五&apos;];</span><br><span class="line">let flag = false;</span><br><span class="line"></span><br><span class="line">let jsx = (&lt;div className=&quot;jsx&quot; style=&#123;style&#125;&gt;</span><br><span class="line">            &#123;/* 条件判断 */&#125;</span><br><span class="line">            &#123;</span><br><span class="line">              flag ? &lt;p&gt;i am &#123;name&#125;&lt;/p&gt; : &lt;p&gt;i am not &#123;name&#125;&lt;/p&gt;</span><br><span class="line">            &#125;</span><br><span class="line">            &#123;/* 变量使用 */&#125;</span><br><span class="line">            jsx...&#123;name&#125;</span><br><span class="line">            &#123;/* 数组循环 */&#125;</span><br><span class="line">            &#123;</span><br><span class="line">              names.map((name, index)=&gt; &lt;p key=&#123;index&#125;&gt;i am &#123;name&#125;&lt;/p&gt;)</span><br><span class="line">            &#125;</span><br><span class="line">          &lt;/div&gt;);</span><br><span class="line"></span><br><span class="line">ReactDOM.render(jsx,document.getElementById(&apos;app&apos;));</span><br></pre></td></tr></table></figure><h4 id="组件"><a href="#组件" class="headerlink" title="组件"></a>组件</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">import React from &apos;react&apos;;</span><br><span class="line">import ReactDOM from &apos;react-dom&apos;;</span><br><span class="line"></span><br><span class="line">// 基础组件</span><br><span class="line">function Componetns() &#123;</span><br><span class="line">  return &lt;h1&gt;i am li&lt;/h1&gt;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">// ES6写法</span><br><span class="line">class ES6Compontnts extends React.Component&#123;</span><br><span class="line">  render() &#123;</span><br><span class="line">    return &lt;h1&gt;i am li&lt;/h1&gt;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;Componetns/&gt;</span><br><span class="line">    &lt;ES6Compontnts/&gt;</span><br><span class="line">  &lt;/div&gt;,</span><br><span class="line">  document.getElementById(&apos;app&apos;)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h4 id="state-amp-props用法"><a href="#state-amp-props用法" class="headerlink" title="state &amp; props用法"></a>state &amp; props用法</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line">import React from &apos;react&apos;;</span><br><span class="line">import ReactDOM from &apos;react-dom&apos;;</span><br><span class="line"></span><br><span class="line">class ES6Compontnts extends React.Component&#123;</span><br><span class="line">  constructor (props) &#123;</span><br><span class="line">    super(props);</span><br><span class="line">    this.state = &#123;</span><br><span class="line">      name: &apos;li&apos;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  render() &#123;</span><br><span class="line">    setTimeout(()=&gt;&#123;</span><br><span class="line">      this.setState(&#123;</span><br><span class="line">        name: &apos;Reson test&apos;</span><br><span class="line">      &#125;)</span><br><span class="line">    &#125;,2000)</span><br><span class="line">    return &lt;h1&gt;i am &#123;this.props.name&#125;&lt;/h1&gt;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;div&gt;</span><br><span class="line">    &lt;ES6Compontnts name=&quot;zhang&quot;/&gt;</span><br><span class="line">  &lt;/div&gt;,</span><br><span class="line">  document.getElementById(&apos;app&apos;)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h4 id="事件"><a href="#事件" class="headerlink" title="事件"></a>事件</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">import React from &apos;react&apos;;</span><br><span class="line">import ReactDOM from &apos;react-dom&apos;;</span><br><span class="line"></span><br><span class="line">class Component extends React.Component&#123;</span><br><span class="line">  constructor(props)&#123;</span><br><span class="line">    super(props);</span><br><span class="line">    this.state = &#123;</span><br><span class="line">      name: &apos;zhang&apos;</span><br><span class="line">    &#125;</span><br><span class="line">    // 为了在回调中使用 `this`，这个绑定是必不可少的</span><br><span class="line">    this.handleClick = this.handleClick.bind(this);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  handleClick() &#123;</span><br><span class="line">    this.setState(state =&gt; (&#123;</span><br><span class="line">      isToggleOn: !state.isToggleOn</span><br><span class="line">    &#125;));</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  render()&#123;</span><br><span class="line">    return (</span><br><span class="line">      &lt;div&gt;</span><br><span class="line">        &lt;button onClick=&#123;this.handleClick&#125;&gt;</span><br><span class="line">          &#123;this.state.isToggleOn ? &apos;ON&apos; : &apos;OFF&apos;&#125;</span><br><span class="line">        &lt;/button&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;Component/&gt;,</span><br><span class="line">  document.getElementById(&apos;app&apos;)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><h4 id="生命周期"><a href="#生命周期" class="headerlink" title="生命周期"></a>生命周期</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br></pre></td><td class="code"><pre><span class="line">import React from &apos;react&apos;;</span><br><span class="line">import ReactDOM from &apos;react-dom&apos;;</span><br><span class="line"></span><br><span class="line">// 生命周期</span><br><span class="line">// Initialization: 组件初始化  setup props and state</span><br><span class="line">// Mounting: 挂载阶段  componentWillMount render componentDidMount</span><br><span class="line">// Updating：运行阶段  </span><br><span class="line">// props &#123;</span><br><span class="line">//   componentWillReceiveProps </span><br><span class="line">//   shouldComponentUpdate </span><br><span class="line">//   componentWillUpdate </span><br><span class="line">//   render </span><br><span class="line">//   componentDidUpdate</span><br><span class="line">// &#125;</span><br><span class="line">// states&#123;</span><br><span class="line">//   shouldComponentUpdate</span><br><span class="line">//   componentWillUpdate</span><br><span class="line">//   render</span><br><span class="line">//   componentDidMount</span><br><span class="line">// &#125;</span><br><span class="line">// Unmounting：卸载阶段  componentWillUnmount</span><br><span class="line">// Error Handling: 错误处理</span><br><span class="line">class Component extends React.Component&#123;</span><br><span class="line">  // 构造函数</span><br><span class="line">  constructor(props)&#123;</span><br><span class="line">    super(props);</span><br><span class="line">    this.state = &#123;</span><br><span class="line">      data: &apos;张三&apos;</span><br><span class="line">    &#125;</span><br><span class="line">    console.log(&apos;初始化数据: constructor&apos;);</span><br><span class="line">  &#125;</span><br><span class="line">  render()&#123;</span><br><span class="line">    console.log(&apos;渲染：render&apos;);</span><br><span class="line">    // return 只有一个根元素</span><br><span class="line">    return &lt;p&gt;</span><br><span class="line">              App: &#123;this.props.data&#125;</span><br><span class="line">              &lt;button onClick=&#123;()=&gt;&#123;this.handlClick()&#125;&#125;&gt;更新组件&#123;this.state.data&#125;&lt;/button&gt;</span><br><span class="line">          &lt;/p&gt;</span><br><span class="line">  &#125;</span><br><span class="line">  // 挂载时</span><br><span class="line">  // 在组件已经被渲染到 DOM 中后运行</span><br><span class="line">  componentDidMount()&#123;</span><br><span class="line">    console.log(&apos;挂载时: componentDidMount&apos;);</span><br><span class="line">  &#125;</span><br><span class="line">  // 处理点击事件</span><br><span class="line">  handlClick() &#123;</span><br><span class="line">    console.log(&apos;更新数据&apos;);</span><br><span class="line">    this.setState(&#123;</span><br><span class="line">      name: &apos;李四&apos;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">  // 将要接收父组件传来的props</span><br><span class="line">  componentWillReceiveProps()&#123;</span><br><span class="line">    console.log(&apos;将要接收父组件传来的props: componentWillReceiveProps&apos;);</span><br><span class="line">  &#125;</span><br><span class="line">  // 子组件是否应该更新</span><br><span class="line">  shouldComponentUpdate()&#123;</span><br><span class="line">    console.log(&apos;子组件是否应该更新: shouldComponentUpdate&apos;);</span><br><span class="line">    return true</span><br><span class="line">  &#125;</span><br><span class="line">  // 组件将要更新</span><br><span class="line">  componentWillUpdate()&#123;</span><br><span class="line">    console.log(&apos;组件将要更新: componentWillUpdate&apos;);</span><br><span class="line">  &#125;</span><br><span class="line">  // 组件更新完成</span><br><span class="line">  componentDidUpdate()&#123;</span><br><span class="line">    console.log(&apos;组件更新完成: componentDidUpdate&apos;);</span><br><span class="line">  &#125;</span><br><span class="line">  // 卸载时</span><br><span class="line">  componentWillUnmount() &#123;</span><br><span class="line">    console.log(&apos;卸载时: componentWillUnmount&apos;);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">class App extends React.Component&#123;</span><br><span class="line">  // 构造函数</span><br><span class="line">  constructor(props)&#123;</span><br><span class="line">    super(props);</span><br><span class="line">    this.state = &#123;</span><br><span class="line">      data: &apos;old 张三&apos;,</span><br><span class="line">      hasChild: true</span><br><span class="line">    &#125;</span><br><span class="line">    console.log(&apos;初始化数据: constructor&apos;);</span><br><span class="line">  &#125;</span><br><span class="line">  onPropsChange()&#123;</span><br><span class="line">    console.log(&apos;更新Props&apos;)</span><br><span class="line">    this.setState(&#123;</span><br><span class="line">      data: &apos;new 张三&apos;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">  onDel() &#123;</span><br><span class="line">    console.log(&apos;销毁子组件&apos;);</span><br><span class="line">    this.setState(&#123;</span><br><span class="line">      hasChild: false</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;</span><br><span class="line">  render()&#123;</span><br><span class="line">    return (</span><br><span class="line">      &lt;div&gt;</span><br><span class="line">        &#123;</span><br><span class="line">          this.state.hasChild ? &lt;Component data=&#123;this.state.data&#125;/&gt; : null</span><br><span class="line">        &#125;</span><br><span class="line">        &lt;button onClick=&#123;()=&gt;&#123;this.onPropsChange()&#125;&#125;&gt;改变Props&lt;/button&gt;</span><br><span class="line">        &lt;button onClick=&#123;()=&gt;&#123;this.onDel()&#125;&#125;&gt;销毁子组件&lt;/button&gt;</span><br><span class="line">      &lt;/div&gt;</span><br><span class="line">    )</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">ReactDOM.render(</span><br><span class="line">  &lt;App/&gt;,</span><br><span class="line">  document.getElementById(&apos;app&apos;)</span><br><span class="line">);</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;JSX语法&quot;&gt;&lt;a href=&quot;#JSX语法&quot; class=&quot;headerlink&quot; title=&quot;JSX语法&quot;&gt;&lt;/a&gt;JSX语法&lt;
      
    
    </summary>
    
    
      <category term="React" scheme="https://liushuai97.github.io/categories/React/"/>
    
    
      <category term="React" scheme="https://liushuai97.github.io/tags/React/"/>
    
  </entry>
  
  <entry>
    <title>浏览器本地存储</title>
    <link href="https://liushuai97.github.io/2019/11/13/%E6%B5%8F%E8%A7%88%E5%99%A8%E6%9C%AC%E5%9C%B0%E5%AD%98%E5%82%A8/"/>
    <id>https://liushuai97.github.io/2019/11/13/浏览器本地存储/</id>
    <published>2019-11-13T02:00:23.000Z</published>
    <updated>2019-11-13T02:01:56.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  // 本地存储</span><br><span class="line">  // cookie</span><br><span class="line">  // 用户端保存请求信息的机制</span><br><span class="line">  // 分号分隔的多个key-value字段</span><br><span class="line">  // 存储在本地的加密文件里</span><br><span class="line">  // 域名和路径的限制</span><br><span class="line"></span><br><span class="line">  // name:cookie 名称</span><br><span class="line">  // domain:cookie 生效的域名</span><br><span class="line">  // path: cookie 生效的路径</span><br><span class="line">  // expires: cookie 过期时间</span><br><span class="line">  // HttpOnly: 用户端不可更改</span><br><span class="line"></span><br><span class="line">  // 浏览器端查看cookie</span><br><span class="line">  document.cookie</span><br><span class="line"></span><br><span class="line">  // cookie添加</span><br><span class="line">  document.cookie = &apos;name=Reson;domain=happymmall.com;path=/index.html;expires:Wed, 13 Nov 2020 01:44:49 GMT&apos;</span><br><span class="line"></span><br><span class="line">  // cookie修改</span><br><span class="line">  document.cookie = &apos;name=Reson1;domain=happymmall.com;path=/index.html&apos;</span><br><span class="line"></span><br><span class="line">  // cookie删除 设定过期时间</span><br><span class="line">  document.cookie = &apos;name=Reson1;domain=happymmall.com;path=/index.html;expires:Wed, 13 Nov 2008 01:44:49 GMT&apos;</span><br><span class="line"></span><br><span class="line">  // session</span><br><span class="line">  // 服务端保存请求信息的机制</span><br><span class="line">  // sessionld通常存放在cookie里</span><br><span class="line">  // 会话由浏览器控制，会话结束，session失效</span><br><span class="line"></span><br><span class="line">  // localStorage</span><br><span class="line">  // H5新特性</span><br><span class="line">  // 有域名限制，不存在作用域概念</span><br><span class="line">  // 只有key-value</span><br><span class="line">  // 没有过期时间</span><br><span class="line">  // 浏览器关闭后不消失</span><br><span class="line"></span><br><span class="line">  // 添加localStorage</span><br><span class="line">  window.localStorage.setItem(&apos;name&apos;,&apos;Rosen&apos;);</span><br><span class="line">  window.localStorage.setItem(&apos;name&apos;,JSON.stringify(&#123;name: &apos;Rosen&apos;&#125;));</span><br><span class="line"></span><br><span class="line">  // 查看localStorage</span><br><span class="line">  window.localStorage.getItem(&apos;name&apos;);</span><br><span class="line"></span><br><span class="line">  // 删除localStorage</span><br><span class="line">  window.localStorage.removeItem(&apos;name&apos;);</span><br><span class="line"></span><br><span class="line">  // sessionStorage</span><br><span class="line">  // 和localStorage极其相似</span><br><span class="line">  // 浏览器关闭后消失</span><br><span class="line">  </span><br><span class="line">  // 添加localStorage</span><br><span class="line">  window.sessionStorage.setItem(&apos;name&apos;,&apos;Rosen&apos;);</span><br><span class="line">  window.sessionStorage.setItem(&apos;name&apos;,JSON.stringify(&#123;name: &apos;Rosen&apos;&#125;));</span><br><span class="line"></span><br><span class="line">  // 查看localStorage</span><br><span class="line">  window.sessionStorage.getItem(&apos;name&apos;);</span><br><span class="line"></span><br><span class="line">  // 删除localStorage</span><br><span class="line">  window.sessionStorage.removeItem(&apos;name&apos;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span cl
      
    
    </summary>
    
    
      <category term="HTML" scheme="https://liushuai97.github.io/categories/HTML/"/>
    
    
      <category term="HTML" scheme="https://liushuai97.github.io/tags/HTML/"/>
    
  </entry>
  
  <entry>
    <title>ES6语法笔记</title>
    <link href="https://liushuai97.github.io/2019/11/13/ES6%E8%AF%AD%E6%B3%95%E7%AC%94%E8%AE%B0/"/>
    <id>https://liushuai97.github.io/2019/11/13/ES6语法笔记/</id>
    <published>2019-11-13T01:25:48.000Z</published>
    <updated>2019-11-13T01:26:18.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  // let定义变量  const 定义常量</span><br><span class="line">  let a = 1;</span><br><span class="line">  a = 2</span><br><span class="line">  console.log(a);</span><br><span class="line"></span><br><span class="line">  const pi = 3.1415926;</span><br><span class="line">  // pi = 4;</span><br><span class="line">  console.log(pi);</span><br><span class="line">  // 不能重复定义</span><br><span class="line">  // let a = 3</span><br><span class="line">  // console.log(a);</span><br><span class="line"></span><br><span class="line">  // const pi = 10;</span><br><span class="line">  // console.log(19);</span><br><span class="line">  // 块级作用域</span><br><span class="line">  if (true) &#123;</span><br><span class="line">    var b = 3</span><br><span class="line">  &#125;</span><br><span class="line">  console.log(b);</span><br><span class="line">  if (true) &#123;</span><br><span class="line">    let c = 3;</span><br><span class="line">  &#125;</span><br><span class="line">  // console.log(c);</span><br><span class="line">  // 不存在变量提升</span><br><span class="line">  let arr = [1, 2, 3, 4, 5, 6, 7, 8];</span><br><span class="line">  for (var i = 0; i &lt; arr.length; i++) &#123;</span><br><span class="line"></span><br><span class="line">  &#125;</span><br><span class="line">  console.log(i);</span><br><span class="line"></span><br><span class="line">  for (let j = 0; j &lt; arr.length; j++) &#123;</span><br><span class="line"></span><br><span class="line">  &#125;</span><br><span class="line">  // console.log(j);</span><br><span class="line">  // -------------------------------------</span><br><span class="line">  // 箭头函数</span><br><span class="line">  // 参数 =&gt; 表达式/语句</span><br><span class="line">  let value = 2;</span><br><span class="line">  let double = x =&gt; 2 * x;</span><br><span class="line">  let treble = x =&gt; &#123;</span><br><span class="line">    return 3 * x;</span><br><span class="line">  &#125;</span><br><span class="line">  console.log(&apos;double&apos;, double(value));</span><br><span class="line">  console.log(&apos;treble&apos;, treble(value));</span><br><span class="line">  // 继承外层作用域</span><br><span class="line">  var obj = &#123;</span><br><span class="line">    commFun: function () &#123;</span><br><span class="line">      console.log(this);</span><br><span class="line">    &#125;,</span><br><span class="line">    arrowFun: () =&gt; &#123;</span><br><span class="line">      console.log(this);</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  obj.commFun();</span><br><span class="line">  obj.arrowFun();</span><br><span class="line">  // 不能用作构造函数</span><br><span class="line">  let Obj = function () &#123; &#125;</span><br><span class="line">  let obj = new Obj();</span><br><span class="line">  let Animal = () =&gt; &#123;</span><br><span class="line"></span><br><span class="line">  &#125;</span><br><span class="line">  let animal = new Animal();</span><br><span class="line">  // 没有prototype属性</span><br><span class="line">  let constFm = function () &#123; &#125;</span><br><span class="line">  let pontFm = () =&gt; &#123; &#125;</span><br><span class="line">  console.log(constFm.prototype);</span><br><span class="line">  console.log(pontFm.prototype);</span><br><span class="line">  // -------------------------------------</span><br><span class="line">  // 模板字符串</span><br><span class="line">  // 反引号标记`</span><br><span class="line">  let str = `</span><br><span class="line">    &lt;div class=&quot;title&quot;&gt;</span><br><span class="line">      &lt;h1&gt;测试标题一&lt;/h1&gt;</span><br><span class="line">    &lt;/div&gt;</span><br><span class="line">  `;</span><br><span class="line">  // document.querySelector(&apos;body&apos;).innerHTML = str;</span><br><span class="line">  // 支持多行字符串</span><br><span class="line">  // 支持变量和表达式</span><br><span class="line">  let name = &apos;Rosen&apos;;</span><br><span class="line">  str += `$&#123;name&#125;`;</span><br><span class="line">  // document.querySelector(&apos;body&apos;).innerHTML = str;</span><br><span class="line"></span><br><span class="line">  let getName = () =&gt; &#123;</span><br><span class="line">    return &apos;Rosen title&apos;</span><br><span class="line">  &#125;</span><br><span class="line">  str += `$&#123;getName()&#125;`;</span><br><span class="line">  // document.querySelector(&apos;body&apos;).innerHTML = str;</span><br><span class="line"></span><br><span class="line">  let names = [&apos;tim&apos;, &apos;dodo&apos;]</span><br><span class="line"></span><br><span class="line">  str += `</span><br><span class="line">    &lt;ul&gt;</span><br><span class="line">      $&#123;names.map(name =&gt;</span><br><span class="line">    `&lt;li&gt;Hi, i am $&#123;name&#125;&lt;/li&gt;`</span><br><span class="line">  ).join(&apos; &apos;)&#125;</span><br><span class="line">    &lt;/ul&gt;</span><br><span class="line">  `</span><br><span class="line">  document.querySelector(&apos;body&apos;).innerHTML = str;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">  // Promise</span><br><span class="line">  // Promise对象 </span><br><span class="line">  new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">    // 异步函数</span><br><span class="line">    $.ajax(&#123;</span><br><span class="line">      url: &apos;http://happymmall.com/user/get_user_info.do&apos;,</span><br><span class="line">      type: &apos;post&apos;,</span><br><span class="line">      // 关键词：resolve,reject,then</span><br><span class="line">      success(res) &#123;</span><br><span class="line">        resolve(res)</span><br><span class="line">      &#125;,</span><br><span class="line">      error(err) &#123;</span><br><span class="line">        reject(err)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;).then(</span><br><span class="line">    (res) =&gt; &#123;</span><br><span class="line">      console.log(&apos;success:&apos;, res);</span><br><span class="line">    &#125;,</span><br><span class="line">    (err) =&gt; &#123;</span><br><span class="line">      console.log(&apos;error:&apos;, err);</span><br><span class="line">    &#125;</span><br><span class="line">  )</span><br><span class="line">  // 链式Promise</span><br><span class="line">  let promiseFn1 = new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">    // 异步函数</span><br><span class="line">    $.ajax(&#123;</span><br><span class="line">      url: &apos;http://happymmall.com/user/get_user_info.do&apos;,</span><br><span class="line">      type: &apos;post&apos;,</span><br><span class="line">      success(res) &#123;</span><br><span class="line">        resolve(res)</span><br><span class="line">      &#125;,</span><br><span class="line">      error(err) &#123;</span><br><span class="line">        reject(err)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  let promiseFn2 = new Promise((resolve, reject) =&gt; &#123;</span><br><span class="line">    // 异步函数</span><br><span class="line">    $.ajax(&#123;</span><br><span class="line">      url: &apos;http://happymmall.com/user/get_cart_prodouct_count.do&apos;,</span><br><span class="line">      type: &apos;post&apos;,</span><br><span class="line">      success(res) &#123;</span><br><span class="line">        resolve(res)</span><br><span class="line">      &#125;,</span><br><span class="line">      error(err) &#123;</span><br><span class="line">        reject(err)</span><br><span class="line">      &#125;</span><br><span class="line">    &#125;)</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line">  promiseFn1.then(() =&gt; &#123;</span><br><span class="line">    console.log(&apos;promiseFn1 success&apos;)</span><br><span class="line">    return promiseFn2;</span><br><span class="line">  &#125;).then(() =&gt; &#123;</span><br><span class="line">    console.log(&apos;promiseFn2 success&apos;)</span><br><span class="line">  &#125;)</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">  // 面向对象-类</span><br><span class="line">  // 关键词：class</span><br><span class="line">  // 语法糖，对应function</span><br><span class="line">  // 构造函数：constructor</span><br><span class="line">  class Animal &#123;</span><br><span class="line">    constructor(name) &#123;</span><br><span class="line">      this.name = name</span><br><span class="line">    &#125;</span><br><span class="line">    getName() &#123;</span><br><span class="line">      return this.name</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  let animal = new Animal(&apos;animal title&apos;);</span><br><span class="line">  console.log(animal.getName());</span><br><span class="line"></span><br><span class="line">  // 面向对象-类的继承</span><br><span class="line">  // extends：类的继承</span><br><span class="line">  // super：调用父类的构造函数 </span><br><span class="line">  class Animal2 &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">      this.name = &apos;张三&apos;</span><br><span class="line">    &#125;</span><br><span class="line">    getName() &#123;</span><br><span class="line">      return this.name</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">  class Cart extends Animal2 &#123;</span><br><span class="line">    constructor() &#123;</span><br><span class="line">      super();</span><br><span class="line">      this.name = &apos;cart&apos;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  let animal2 = new Animal2();</span><br><span class="line">  let cart = new Cart();</span><br><span class="line"></span><br><span class="line">  console.log(animal2.getName());</span><br><span class="line">  console.log(cart.getName());</span><br><span class="line"></span><br><span class="line">  // 面向对象-对象</span><br><span class="line">  // 对象里属性的简写</span><br><span class="line">  // 对象里方法的简写</span><br><span class="line">  // 属性名可以为表达式</span><br><span class="line">  // 其他扩展</span><br><span class="line">  var name = &quot;Reson&quot;,</span><br><span class="line">    age = 18;</span><br><span class="line"></span><br><span class="line">  // old</span><br><span class="line">  var obj = &#123;</span><br><span class="line">    name: name,</span><br><span class="line">    age: age,</span><br><span class="line">    getName: function () &#123;</span><br><span class="line">      return this.name</span><br><span class="line">    &#125;,</span><br><span class="line">    getAge: function () &#123;</span><br><span class="line">      return this.age</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  // news</span><br><span class="line">  let name1 = &quot;Reson&quot;,</span><br><span class="line">    age1 = 18;</span><br><span class="line"></span><br><span class="line">  let obj1 = &#123;</span><br><span class="line">    // 变量名可以用作对象属性名</span><br><span class="line">    name1,</span><br><span class="line">    age1,</span><br><span class="line">    // 对象方法可以简写</span><br><span class="line">    getName() &#123;</span><br><span class="line">      return this.name1</span><br><span class="line">    &#125;,</span><br><span class="line">    // 表达式作为属性方法名</span><br><span class="line">    [&apos;get&apos; + &apos;Age&apos;]() &#123;</span><br><span class="line">      return this.age1;</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  // Object对象的扩展</span><br><span class="line">  Object.keys(obj1);</span><br><span class="line">  Object.assign(&#123; a: 1 &#125;, &#123; a: 2, b: 2 &#125;)  // 浅拷贝</span><br><span class="line"></span><br><span class="line">  // ES6模块化</span><br><span class="line">  // 解决一个复杂问题时，自上而下逐层把系统划分成若干模块的过程</span><br><span class="line">  // CommonJS,AMD,CMD</span><br><span class="line">  // 关键词 export import</span><br><span class="line"></span><br><span class="line">  // 基本指令：let const</span><br><span class="line">  // 箭头函数：value =&gt; return value + 1</span><br><span class="line">  // 模板字符串： `Hell $&#123;name&#125;`</span><br><span class="line">  // promise: Promise, resolve, reject, then</span><br><span class="line">  // 面向对象： class, extends, super, constructor</span><br><span class="line">  // 模块化：export, import, as, default</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span cl
      
    
    </summary>
    
    
      <category term="ES6" scheme="https://liushuai97.github.io/categories/ES6/"/>
    
    
      <category term="ES6" scheme="https://liushuai97.github.io/tags/ES6/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript-自测题16</title>
    <link href="https://liushuai97.github.io/2019/11/01/JavaScript-%E8%87%AA%E6%B5%8B%E9%A2%9816/"/>
    <id>https://liushuai97.github.io/2019/11/01/JavaScript-自测题16/</id>
    <published>2019-11-01T05:33:07.000Z</published>
    <updated>2019-11-06T06:37:18.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><h4 id="理解元编程"><a href="#理解元编程" class="headerlink" title="理解元编程"></a>理解元编程</h4><p>Symbol、Reflect 和 Proxy 是属于 ES6 元编程范畴的，能“介入”的对象底层操作进行的过程中，并加以影响。元编程中的 元 的概念可以理解为 程序 本身。</p><p>“元编程就是改变程序原本的运行方式”</p><p>Javascript 中，eval、new Function()便是两个可以用来进行元编程的特性。</p><h4 id="ES6-下的元编程：Symbol"><a href="#ES6-下的元编程：Symbol" class="headerlink" title="ES6 下的元编程：Symbol"></a>ES6 下的元编程：Symbol</h4><p>Symbols 是 ES6 一个全新的 API，它是实现了的反射（Reflection within implementation）—— 你将 Symbols 应用到你已有的类和对象上去改变它们的行为。</p><p>Symbols 是新的原始类型（primitive）。就像是 Number、String、和 Boolean 一样。Symbols 具有一个 Symbol 函数用于创建 Symbol。与别的原始类型不同，Symbols 没有字面量语法（例如，String 有 ”）—— 创建 Symbol 的唯一方式是使用类似构造函数而又非构造函数的 Symbol 函数：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">Symbol(); // symbol</span><br><span class="line">console.log(Symbol()); // 输出 &quot;Symbol()&quot; 至控制台</span><br><span class="line">assert(typeof Symbol() === &apos;symbol&apos;)</span><br><span class="line">// 类似构造函数而又非构造函数的 Symbol 函数</span><br><span class="line">new Symbol(); // TypeError: Symbol is not a constructor</span><br></pre></td></tr></table></figure><h4 id="Symbols-能被用作对象的-key"><a href="#Symbols-能被用作对象的-key" class="headerlink" title="Symbols 能被用作对象的 key"></a>Symbols 能被用作对象的 key</h4><p>Symbols 能用作对象的 key （类似字符串 key），这意味着你可以分配无限多的具有唯一性的 Symbols 到一个对象上，这些 key 保证不会和现有的字符串 key 冲突，或者和其他 Symbol key 冲突。</p><p>并且，继续划重点，Symbols key 无法通过 for in、for of 或者 Object.getOwnPropertyNames 获得 —— 获得它们的唯一方式是 Object.getOwnPropertySymbols。</p><p>这意味着 Symbols 能够给对象提供一个隐藏层，帮助对象实现了一种全新的目的 —— 属性不可迭代，也不能够通过现有的反射工具获得，并且能被保证不会和对象任何已有属性冲突。</p><p>但是，这里也有个例外：Symbol.for()</p><p>JavaScript 也有另一个创建 Symbol 的方式来轻易地实现 Symbol 的获得和重用：Symbol.for()。该方法在 “全局 Symbol 注册中心” 创建了一个 Symbol。额外注意的一点：这个注册中心也是跨域的，意味着 iframe 或者 service worker 中的 Symbol 会与当前 frame Symbol 相等</p><ol><li>Symbols 无法通过现有的反射工具读取。</li></ol><p>你需要一个新的方法 Object.getOwnPropertySymbols() 来访问对象上的 Symbols，这让 Symbol 适合存储那些你不想让别人直接获得的信息。</p><ol start="2"><li>Symbols 不是私有的。</li></ol><p>作为双刃剑的另一面 —— 对象上所有的 Symbols 都可以直接通过 Object.getOwnPropertySymbols() 获得 —— 这不利于我们使用 Symbol 存储一些真正需要私有化的值。</p><ol start="3"><li>Symbols 不总是唯一的。</li></ol><p>Symbol.for() 将为你返回一个不唯一的 Symbol。不要总认为 Symbol 具有唯一性，除非你自己能够保证它的唯一性。</p><h4 id="Symbol的作用"><a href="#Symbol的作用" class="headerlink" title="Symbol的作用"></a>Symbol的作用</h4><ol><li><p>作为一个可替换字符串或者整型使用的唯一值</p></li><li><p>作为一个对象中放置元信息（metadata）的场所（记住，Symbols 不是私有的）</p></li><li><p>给予开发者在 API 中为对象添加钩子（hook）的能力</p></li></ol><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line">// 从 API 的 Symbols 常量中获得这个充满魔力的 Inspect Symbol</span><br><span class="line">var inspect = console.Symbols.INSPECT; // 这是一个 Symbols 对象</span><br><span class="line"></span><br><span class="line">var myVeryOwnObject = &#123;&#125;;</span><br><span class="line">console.log(myVeryOwnObject); // 日志 `&#123;&#125;`</span><br><span class="line"></span><br><span class="line">myVeryOwnObject[inspect] = function () &#123; return &apos;DUUUDE&apos;; &#125;;</span><br><span class="line">console.log(myVeryOwnObject); // 日志输出 `DUUUDE`</span><br></pre></td></tr></table></figure><p>钩子实现大致如下：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">console.log = function (…items) &#123;</span><br><span class="line">  var output = &apos;&apos;;</span><br><span class="line">  for(const item of items) &#123;</span><br><span class="line">    if (typeof item[console.Symbols.INSPECT] === &apos;function&apos;) &#123;</span><br><span class="line">        output += item[console.Symbols.INSPECT](item);</span><br><span class="line">    &#125; else &#123;</span><br><span class="line">        output += console.inspect[typeof item](item);</span><br><span class="line">    &#125;</span><br><span class="line">    output += &apos;  &apos;;</span><br><span class="line">  &#125;</span><br><span class="line">  process.stdout.write(output + &apos;\n&apos;);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><ul><li>PS：钩子是什么？</li></ul><p>提供一个可以影响默认的(或原有的)流程(机制)的时机</p><p>通常就是：一个库、一个框架、一个系统或一种语言，提供一个对外公开的接口，通过这个接口，用户能够影响库、框架、系统或程序的行为。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">const arr = [4, 5, 6, 7, 8, 9];</span><br><span class="line">//定义一个尽在奇数索引地方生产值</span><br><span class="line">arr[Symbol.iterator] = function* () &#123;</span><br><span class="line">    let idx = 1;</span><br><span class="line">    console.table(this);</span><br><span class="line">    do &#123;</span><br><span class="line">        yield this[idx];</span><br><span class="line">    &#125; while ((idx += 2) &lt; this.length)</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">for (const v of arr) &#123;</span><br><span class="line">    console.log(&apos;v&apos;, v);</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4 id="Proxy"><a href="#Proxy" class="headerlink" title="Proxy"></a>Proxy</h4><p>Proxy 对象用于定义基本操作的自定义行为（如属性查找，赋值，枚举，函数调用等）。</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">let person = &#123;</span><br><span class="line">    age: 27</span><br><span class="line">&#125;;</span><br><span class="line">const validator = &#123;</span><br><span class="line">    set(target, key, value) &#123;</span><br><span class="line">        console.log(target);</span><br><span class="line">        if (typeof value !== &quot;number&quot; || Number.isNaN(value)) &#123;</span><br><span class="line">            throw new TypeError(&quot;年龄必须是一个数字&quot;);</span><br><span class="line">        &#125;</span><br><span class="line">        return true;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line">const proxy = new Proxy(person, validator);</span><br><span class="line">proxy.age = &quot;🇨🇳&quot;;</span><br><span class="line">console.log(123);</span><br></pre></td></tr></table></figure><h4 id="Reflect"><a href="#Reflect" class="headerlink" title="Reflect"></a>Reflect</h4><p>为操作对象而提供的新API</p><ul><li><p>将Object对象的属于语言内部的方法放到Reflect对象上，即从Reflect对象上拿Object对象内部方法。</p></li><li><p>将用 老Object方法 报错的情况，改为返回false</p></li></ul><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">function Tree() &#123;</span><br><span class="line">    return new Proxy(&#123;&#125;, handler);</span><br><span class="line">&#125;</span><br><span class="line">const handler = &#123;</span><br><span class="line">    get(target, key, receiver) &#123;</span><br><span class="line">        if (!(key in target)) &#123;</span><br><span class="line">            //自动创建一个树</span><br><span class="line">            target[key] = Tree();</span><br><span class="line">        &#125;</span><br><span class="line">        return Reflect.get(target, key, receiver);</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">let tree = Tree();</span><br><span class="line">tree.yideng.student.a = &quot;小牛🐂&quot;;</span><br><span class="line">console.log(tree);</span><br></pre></td></tr></table></figure><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;h4 id=&quot;理解元编程&quot;&gt;&lt;a href=&quot;#理解元编程&quot; class=&quot;headerlink&quot; title=&quot;理解元编程&quot;&gt;&lt;/a&gt;理解元编程&lt;
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/categories/JavaScript/"/>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/tags/JavaScript/"/>
    
  </entry>
  
  <entry>
    <title>JavaScript-自测题15</title>
    <link href="https://liushuai97.github.io/2019/11/01/JavaScript-%E8%87%AA%E6%B5%8B%E9%A2%9815/"/>
    <id>https://liushuai97.github.io/2019/11/01/JavaScript-自测题15/</id>
    <published>2019-11-01T02:41:39.000Z</published>
    <updated>2019-11-01T03:00:50.000Z</updated>
    
    <content type="html"><![CDATA[<!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">&#123;</span><br><span class="line">  var a = 1;</span><br><span class="line">  const b = 2;</span><br><span class="line">  function test()&#123;&#125;</span><br><span class="line">  test = 3;</span><br><span class="line">  console.log(typeof test);   // number</span><br><span class="line">&#125;</span><br><span class="line">console.log(a); // 1</span><br><span class="line">console.log(typeof test);  // function</span><br><span class="line">console.log(b); // b is not defined</span><br></pre></td></tr></table></figure><p>执行结果：</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">number</span><br><span class="line">1</span><br><span class="line">function</span><br><span class="line">Uncaught ReferenceError: b is not defined</span><br></pre></td></tr></table></figure><p>解析：</p><ol><li>test = 3 console.log(type test)为：number</li><li>var a 不存在块级作用域限制，所以 console.log(a)为：1</li><li>test() 函数声明被提升，所以外部console.log(typeof test)为：function</li><li>const b 存在块级作用域限制，所以 b is not defined</li></ol><!-- rebuild by neat -->]]></content>
    
    <summary type="html">
    
      
      
        &lt;!-- build time:Fri Aug 28 2020 16:45:28 GMT+0800 (GMT+08:00) --&gt;&lt;figure class=&quot;highlight plain&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span cl
      
    
    </summary>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/categories/JavaScript/"/>
    
    
      <category term="JavaScript" scheme="https://liushuai97.github.io/tags/JavaScript/"/>
    
  </entry>
  
</feed>
