<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Landerqi Blog</title>
  
  <subtitle>格调、风度、和谐、节奏之美均源自简洁...</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://landerqi.com/"/>
  <updated>2021-05-31T07:33:41.621Z</updated>
  <id>http://landerqi.com/</id>
  
  <author>
    <name>Landerqi</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>Mildom首页性能优化方案</title>
    <link href="http://landerqi.com/2021/05/31/Mildom%E9%A6%96%E9%A1%B5%E6%80%A7%E8%83%BD%E4%BC%98%E5%8C%96%E6%96%B9%E6%A1%88/"/>
    <id>http://landerqi.com/2021/05/31/Mildom首页性能优化方案/</id>
    <published>2021-05-31T06:42:26.000Z</published>
    <updated>2021-05-31T07:33:41.621Z</updated>
    
    <content type="html"><![CDATA[<!-- toc --><ul><li><a href="#%E9%A2%84%E6%B8%B2%E6%9F%93">预渲染</a></li><li><a href="#%E5%9B%BE%E7%89%87%E8%B5%84%E6%BA%90%E4%BC%98%E5%8C%96">图片资源优化</a></li><li><a href="#%E4%BB%A3%E7%A0%81%E4%BC%98%E5%8C%96">代码优化</a></li><li><a href="#pwa%E6%B8%90%E8%BF%9B%E5%BC%8Fweb%E5%BA%94%E7%94%A8">PWA(渐进式web应用)</a></li><li><a href="#%E5%8F%82%E8%80%83">参考：</a></li></ul><!-- tocstop --><h3><span id="预渲染">预渲染</span></h3><p>无需使用web 服务器实时动态编译 HTML，不需要服务器支持。在构建时 (build time) 简单地生成针对特定路由的静态HTML 文件。这个提高效果应该会比较明显。</p><ol><li><p>利用<code>prerender-spa-plugin</code>，生成模板。<code>style components</code>需要升级到5.x以上版本，这样才支持css提取。注意需要配置：<code>renderAfterDocumentEvent: &#39;render-event&#39;，renderAfterTime: 5000</code>，在index.js入口处监听dom loaded，然后延迟5s触法自定义事件‘render-event’，否则无法请求到数据；</p></li><li><p>生成模板的时间需要：</p> <figure class="highlight gradle"><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></pre></td><td class="code"><pre><span class="line">   injectProperty: <span class="string">&#x27;__PRERENDER_INJECTED&#x27;</span>,</span><br><span class="line">   <span class="comment">// Optional - Any values you&#x27;d like your app to have access to via window.injectProperty.</span></span><br><span class="line">   <span class="keyword">inject</span>: &#123;</span><br><span class="line">        prerender: <span class="keyword">true</span>,</span><br><span class="line">        isDarkMode: process.env.THEME === <span class="string">&#x27;dark&#x27;</span>,</span><br><span class="line">​    &#125;</span><br></pre></td></tr></table></figure><p>注入全局变量，然后通过npm run 命令传参生成 日间、夜间 两个模板；</p></li><li><p>生成完模板之后，拷贝到 client/pages/prerender目录下保存（index.white.html、index.dark.html）；</p></li></ol><span id="more"></span><ol start="4"><li><p>在jenkens上运行npm run prod命令之后，会在static目录上生成index.tmpl.html文件，这个文件里面的css, js都已经被webpack注入进去，我们需要做的是把client/pages/prerender目录下保存的样式和Dom，提取出来，注入到index.tmpl.html文件，同时在static目录下生成index.white.html、index.dark.html两个文件。</p></li><li><p>把用户设置的主题保存在cookie中，访问页面的时候go server根据cookie中主题的值，选择返回 日间、夜间 模板。</p></li></ol><p><strong>注意：</strong></p><ol><li><p>首页用到的组件一定要写骨架，因为首页数据是动态的，渲染出的数据只能是当时的数据片段，这样显然不行，所以我们需要在预渲染的时候注入全局变量，当判断到是预渲染时，则渲染骨架；</p></li><li><p>自定义事件一定要延迟触发，否则无法生成内容，这里很多资料都没提到，有点坑:</p> <figure class="highlight coffeescript"><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"> <span class="built_in">window</span>.addEventListener(<span class="string">&#x27;DOMContentLoaded&#x27;</span>, <span class="function"><span class="params">()</span>=&gt;</span>&#123;</span><br><span class="line"></span><br><span class="line"> <span class="built_in">setTimeout</span>(<span class="function"><span class="params">()</span> =&gt;</span> &#123;</span><br><span class="line"></span><br><span class="line">  <span class="built_in">document</span>.dispatchEvent(<span class="keyword">new</span> Event(<span class="string">&#x27;render-event&#x27;</span>));</span><br><span class="line"></span><br><span class="line"> &#125;, <span class="number">5000</span>);</span><br><span class="line"></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure></li><li><p>要避免闪烁，当判断root element下有子节点的时候需要用 hydrate方法替代render方法；</p></li><li><p>首页需要特定的 RouteLoaderIndex，避免闪烁；</p></li><li><p>go server需要判断只有匹配到首页才返回日间、夜间模板，其他则返回之前的正常模板。</p></li></ol><h3><span id="图片资源优化">图片资源优化</span></h3><ol><li>使用合适的图片大小，目前首页图片都是1，200kb的，而且有的用户头像甚至达到了700kb；</li><li>使用JPEG 2000、JPEG XR 和 WebP 等新图片格式，压缩率更好；</li><li>Banner图片压缩，是否流程化，是否在cms上传源头就加上大小限制；</li><li>延长图片等静态资源缓存时间：wia.mildom.com下的图片是1天，<a href="http://www.mildom.com下的图片、js、css是15天,vpic.mildom.com下的图片等是30天,up.mildom.com下的是90天./">www.mildom.com下的图片、js、css是15天，vpic.mildom.com下的图片等是30天，up.mildom.com下的是90天。</a></li><li>使用JPEG 2000、JPEG XR 和 WebP 等新图片格式，压缩率更好；（咨询，不一定做）</li></ol><h3><span id="代码优化">代码优化</span></h3><p>分析工具：<a href="https://developers.google.com/speed/pagespeed/insights/?url=https://www.mildom.com/&tab=desktop">Pagespeed Insights</a>。</p><p>chunk_main.js体积很大，目前看这个js有788kb，这个js加载完之前，一直白屏。</p><ol><li><p>不使用服务器端直出，可考虑使用 <code>React.lazy()</code><sup> [1]</sup>拆分 JavaScript  代码。或者使用第三方库（如 <a href="https://www.smooth-code.com/open-source/loadable-components/docs/getting-started/">loadable-components</a>）拆分代码；</p></li><li><p>首屏外资源延迟加载；</p></li><li><p>首屏展示没有用到的组件懒加载；</p></li><li><p>减少主线程工作：优化第三方js(cdn，公共组件抽离)、使用Web workers<sup>[2]</sup>；</p></li><li><p>优化Largest Contentful Paint (<a href="https://web.dev/lighthouse-largest-contentful-paint/?utm_source=lighthouse&utm_medium=unknown">LCP，最大内容渲染时间</a>)<sup>[3]</sup>;</p></li><li><p>避免出现长时间运行的主线程任务，可利用“火焰图“分析<sup>[4]</sup>;</p></li><li><p>优化Cumulative Layout Shift (CLS)<sup>[5]</sup>。</p></li></ol><h3><span id="pwa渐进式web应用">PWA(渐进式web应用)</span></h3><p>PWA应用是指那些使用指定技术和标准模式来开发的web应用，这将同时赋予它们web应用和原生应用的特性。</p><p>引入<a href="https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API">Service Workers</a>来进行缓存, 以此来节省带宽和时间。</p><h3><span id="参考">参考：</span></h3><p>[1] <a href="https://web.dev/code-splitting-suspense/?utm_source=lighthouse&utm_medium=unknown">Code splitting with React.lazy and Suspense</a></p><p>[2] <a href="https://web.dev/off-main-thread/">Use web workers to run JavaScript off the browser’s main thread</a></p><p>[3] <a href="https://web.dev/lcp/#how-to-improve-largest-contentful-paint-on-your-site">How to improve largest contentful paint on your site</a></p><p>[4] <a href="https://web.dev/long-tasks-devtools/?utm_source=lighthouse&utm_medium=unknown">Are long JavaScript tasks delaying your Time to Interactive?</a></p><p>[5] <a href="https://web.dev/cls/#how-to-improve-cls">How to improve CLS</a></p>]]></content>
    
    <summary type="html">
    
      &lt;!-- toc --&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#%E9%A2%84%E6%B8%B2%E6%9F%93&quot;&gt;预渲染&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%9B%BE%E7%89%87%E8%B5%84%E6%BA%90%E4%BC%98%E5%8C%96&quot;&gt;图片资源优化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E4%BB%A3%E7%A0%81%E4%BC%98%E5%8C%96&quot;&gt;代码优化&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#pwa%E6%B8%90%E8%BF%9B%E5%BC%8Fweb%E5%BA%94%E7%94%A8&quot;&gt;PWA(渐进式web应用)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#%E5%8F%82%E8%80%83&quot;&gt;参考：&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;!-- tocstop --&gt;

&lt;h3 id=&quot;预渲染&quot;&gt;&lt;a href=&quot;#预渲染&quot; class=&quot;headerlink&quot; title=&quot;预渲染&quot;&gt;&lt;/a&gt;预渲染&lt;/h3&gt;&lt;p&gt;无需使用web 服务器实时动态编译 HTML，不需要服务器支持。在构建时 (build time) 简单地生成针对特定路由的静态HTML 文件。这个提高效果应该会比较明显。&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;p&gt;利用&lt;code&gt;prerender-spa-plugin&lt;/code&gt;，生成模板。&lt;code&gt;style components&lt;/code&gt;需要升级到5.x以上版本，这样才支持css提取。注意需要配置：&lt;code&gt;renderAfterDocumentEvent: &amp;#39;render-event&amp;#39;，renderAfterTime: 5000&lt;/code&gt;，在index.js入口处监听dom loaded，然后延迟5s触法自定义事件‘render-event’，否则无法请求到数据；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;生成模板的时间需要：&lt;/p&gt;
 &lt;figure class=&quot;highlight gradle&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;   injectProperty: &lt;span class=&quot;string&quot;&gt;&amp;#x27;__PRERENDER_INJECTED&amp;#x27;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;comment&quot;&gt;// Optional - Any values you&amp;#x27;d like your app to have access to via window.injectProperty.&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;   &lt;span class=&quot;keyword&quot;&gt;inject&lt;/span&gt;: &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        prerender: &lt;span class=&quot;keyword&quot;&gt;true&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        isDarkMode: process.env.THEME === &lt;span class=&quot;string&quot;&gt;&amp;#x27;dark&amp;#x27;&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;​    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;注入全局变量，然后通过npm run 命令传参生成 日间、夜间 两个模板；&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;生成完模板之后，拷贝到 client/pages/prerender目录下保存（index.white.html、index.dark.html）；&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
      <category term="javascript" scheme="http://landerqi.com/tags/javascript/"/>
    
      <category term="前端" scheme="http://landerqi.com/tags/%E5%89%8D%E7%AB%AF/"/>
    
  </entry>
  
  <entry>
    <title>Vue VS React</title>
    <link href="http://landerqi.com/2020/12/31/Vue-VS-React/"/>
    <id>http://landerqi.com/2020/12/31/Vue-VS-React/</id>
    <published>2020-12-31T10:01:57.000Z</published>
    <updated>2021-05-31T06:52:45.734Z</updated>
    
    <content type="html"><![CDATA[<p>之前公司用的都是Vue，最近在新公司使用的是React。基于自己5个月来使用React的一些感受，把React 和 Vue做了一个简单的对比。</p><p><strong>Vue 组件：</strong></p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  <span class="xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;app&quot;</span>&gt;</span></span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span></span><br><span class="line"><span class="javascript"><span class="xml"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="attr">components</span>: &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="attr">props</span>: &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  data () &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">    <span class="keyword">return</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">    &#125;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="attr">computed</span>: &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="attr">watch</span>: &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  created () &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  mounted () &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="attr">methods</span>: &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">&#125;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">style</span> <span class="attr">scoped</span> <span class="attr">lang</span>=<span class="string">&quot;scss&quot;</span>&gt;</span></span></span><br><span class="line"><span class="xml"></span></span><br><span class="line"><span class="xml"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><span id="more"></span><h3><span id="数据流不同">数据流不同</span></h3><ul><li>Vue 通过 getter/setter 以及一些函数的劫持，能精确知道数据变化，不需要特别的优化就能达到很好的性能</li><li>React 默认是通过比较引用的方式进行的，如果不优化（PureComponent/shouldComponentUpdate）可能导致大量不必要的VDOM的重新渲染</li></ul><p><strong>Vue 使用的是可变数据，而React更强调数据的不可变：</strong></p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glkeceiqhwj30pm0cl43g.jpg" alt="image-20200816154047781"><h3><span id="react高阶组件hoc与-vue-mixins">React高阶组件（HOC）与 Vue mixins</span></h3><p><strong>Hoc:</strong> 高阶组件（HOC）是 React 中用于<strong>复用组件逻辑</strong>的一种高级技巧。HOC 自身不是 React API 的一部分，它是一种基于 React 的组合特性而形成的设计模式。</p><p><strong>Vue mixins:</strong></p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 检查登录 mixin模块</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="keyword">import</span> &#123; getLoginState, goToLogin &#125; <span class="keyword">from</span> <span class="string">&#x27;@/common/xxApi&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  data () &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">      <span class="attr">loginState</span>: <span class="literal">false</span>, <span class="comment">// 登录状态</span></span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="keyword">async</span> created () &#123;</span><br><span class="line">    <span class="built_in">this</span>.loginState = <span class="keyword">await</span> getLoginState()</span><br><span class="line">  &#125;,</span><br><span class="line">  mounted () &#123;</span><br><span class="line">    <span class="comment">// block</span></span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    <span class="comment">// 登录检查，通过返回 true，不通过返回 false</span></span><br><span class="line">    checkLogin () &#123;</span><br><span class="line">      <span class="comment">// if (__DEV__) return true</span></span><br><span class="line"></span><br><span class="line">      <span class="keyword">if</span> (<span class="built_in">this</span>.loginState) &#123; <span class="comment">// 已登录</span></span><br><span class="line">        <span class="keyword">return</span> <span class="literal">true</span></span><br><span class="line">      &#125; <span class="keyword">else</span> &#123; <span class="comment">// 未登录</span></span><br><span class="line">        <span class="built_in">console</span>.log(<span class="string">&#x27;[checkLogin] 未登录&#x27;</span>)</span><br><span class="line">        goToLogin()</span><br><span class="line">        <span class="keyword">return</span> <span class="literal">false</span></span><br><span class="line">      &#125;</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"></span><br><span class="line"><span class="comment">// index.vue</span></span><br><span class="line"><span class="keyword">import</span> &#123; checkLogin &#125; <span class="keyword">from</span> <span class="string">&#x27;@/common/mixins&#x27;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span><br><span class="line">  <span class="attr">components</span>: &#123;</span><br><span class="line">    ...</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">mixins</span>: [checkLogin],</span><br><span class="line">  data () &#123;</span><br><span class="line">    <span class="keyword">return</span> &#123;</span><br><span class="line">     ...</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">computed</span>: &#123;</span><br><span class="line">    ...</span><br><span class="line">  &#125;,</span><br><span class="line">  mounted () &#123;</span><br><span class="line">    ...</span><br><span class="line">  &#125;,</span><br><span class="line">  <span class="attr">methods</span>: &#123;</span><br><span class="line">    ...</span><br><span class="line">    &#125;,</span><br><span class="line">  &#125;,</span><br><span class="line">&#125;</span><br><span class="line">&lt;/script&gt;</span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">style</span>&gt;</span></span></span><br><span class="line"><span class="xml">  ...</span></span><br><span class="line"><span class="xml"><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><h3><span id="组件通信">组件通信</span></h3><h4><span id="vue">Vue:</span></h4><ol><li><p>父组件通过 props 向子组件传递数据或者回调：</p><figure class="highlight javascript"><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">父组件： &lt;child value = <span class="string">&#x27;传递的数据&#x27;</span> /&gt;</span><br><span class="line"></span><br><span class="line">子组件: props[<span class="string">&#x27;value&#x27;</span>],接收数据,接受之后使用和data中定义数据使用方式一样</span><br><span class="line"></span><br></pre></td></tr></table></figure></li></ol><ol start="2"><li><p>子组件通过事件向父组件发送消息（$emit）：</p><figure class="highlight javascript"><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">父组件： &lt;child @receive = <span class="string">&#x27;receive&#x27;</span> /&gt;</span><br><span class="line"></span><br><span class="line">子组件: <span class="built_in">this</span>.$emit(<span class="string">&#x27;receive&#x27;</span>,<span class="string">&#x27;传递的数据&#x27;</span>)</span><br></pre></td></tr></table></figure></li></ol><ol start="3"><li><p>兄弟组件传值：</p><figure class="highlight javascript"><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">通过中央通信 <span class="keyword">let</span> bus = <span class="keyword">new</span> Vue()</span><br><span class="line"></span><br><span class="line">A：methods :&#123; 函数&#123;bus.$emit(‘自定义事件名’，数据)&#125; 发送</span><br><span class="line"></span><br><span class="line">B：created （）&#123;bus.$on(‘A发送过来的自定义事件名’，函数)&#125; 进行数据接收</span><br><span class="line"></span><br><span class="line">或者使用：vuex</span><br></pre></td></tr></table></figure></li></ol><ol start="4"><li>通过 V2.2.0 中新增的 provide/inject 来实现父组件向子组件注入数据，可以跨越多个层级。</li></ol><h4><span id="react">React:</span></h4><ol><li>父组件通过 props 可以向子组件传递数据或者回调；</li><li>可以通过 context 进行跨层级的通信，和 provide/inject 起到的作用差不多。</li></ol><p><strong>React 本身并不支持自定义事件，需要使用第三方库，如：eventemitter3。</strong></p><h3><span id="vuex-与-redux">Vuex 与 Redux</span></h3><h4><span id="vuex">Vuex:</span></h4><ol><li>使用 dispatch 和 commit 提交更新；</li><li>通过 mapState 或者直接通过 this.$store 来读取数据。</li></ol><h4><span id="redux">Redux:</span></h4><ol><li>Redux 中，我们每一个组件都需要显示的用 connect 把需要的 props 和 dispatch 连接起来；</li><li>Redux 中只能进行 dispatch，并不能直接调用 reducer 进行修改。而Vuex可以 dispatch action 也可以 commit updates。</li></ol><ul><li><strong>Redux 使用的是不可变数据，而Vuex的数据是可变的。Redux每次都是用新的state替换旧的state，而Vuex是直接修改</strong></li><li><strong>Redux 在检测数据变化的时候，是通过 diff 的方式比较差异的，而Vuex其实和Vue的原理一样，是通过 getter/setter来比较的（如果看Vuex源码会知道，其实他内部直接创建一个Vue实例用来跟踪数据变化）</strong></li></ul><p><strong>而这两点的区别，其实也是因为 React 和 Vue的设计理念上的区别。React更偏向于构建稳定大型的应用，非常的科班化。相比之下，Vue更偏向于简单迅速的解决问题，更灵活，不那么严格遵循条条框框。因此也会给人一种大型项目用React，小型项目用 Vue 的感觉。</strong></p><h3><span id="其他小差异">其他小差异：</span></h3><ol><li><p>vue提供很多指令，如 <code>:class</code>可以根据不同条件绑定不同的class name，react中使用<code>classnames</code>库存来实现此功能；</p></li><li><p>vue在子组件定义中，直接声明接收的props值类型及默认值，react components中是使用<code>prop-types</code>库；</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// vue</span></span><br><span class="line"><span class="attr">props</span>: &#123;</span><br><span class="line">  <span class="attr">type</span>: xxx,</span><br><span class="line">  <span class="attr">default</span>: xxx,</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line"><span class="comment">// react</span></span><br><span class="line"><span class="keyword">import</span> PropTypes <span class="keyword">from</span> <span class="string">&quot;prop-types&quot;</span>;</span><br><span class="line">xxx.propTypes = &#123;</span><br><span class="line">   <span class="attr">xxx</span>: PropTypes.array,</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure></li><li><p>比如发送事件，react也是需要使用第三方库实现。</p></li></ol><p><strong>从这些小差异，我感觉React其实更接近一个纯粹的UI框架，框架本身不耦合其他无关的东西，开发者用到的时候再自行使用。</strong></p><p><strong>而Vue则像一个高度定制的框架，很多东西他框架本身就集成进去了，所以开发者使用的时候更方便一点。感觉他更加一个工具，类似IDE ？可能这就是为什么有的人说Vue更容易上手的原因。</strong></p><p><strong>而且在我使用中，用React开发，对开发者要求更高，很多东西框架并不会帮你处理，需要开发者自行考虑。其实写React能使开发者更关注语言本身。</strong></p><p>就像bind this这个，文档上写了是javascript语言特性，自己手动绑定就好，所以react也不会多此一举帮你绑定修复：</p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glkecxv4ohj30qz08oq4u.jpg" alt="image-20200815103130911"><p><a href="https://www.smashingmagazine.com/2014/01/understanding-javascript-function-prototype-bind/">how function work in Javascript</a></p><p><strong>从这些点可以看出两个框架从设计上来说其实就不太一样，从他们各自github上的star数量上就可以证明了两个框架都非常优秀。</strong></p><p><img src="https://tva1.sinaimg.cn/large/0081Kckwgy1glkecyj55uj30je09tmyi.jpg" alt="image-20200816152151887"></p><h1><span id="vue使用经验">Vue使用经验</span></h1><h3><span id="为什么vue组件中data必须是一个函数">为什么Vue组件中data必须是一个函数</span></h3><p>对象为引用类型，当复用组件时，由于数据对象都指向同一个data对象，当在一个组件中修改data时，其他重用的组件中的data会同时被修改；而使用返回对象的函数，由于每次返回的都是一个新对象（Object的实例），引用地址不同，则不会出现这个问题。</p><h3><span id="vue中v-if和v-show有什么区别"><strong>vue中v-if和v-show有什么区别？</strong></span></h3><p>v-if和v-show看起来似乎差不多，当条件不成立时，其所对应的标签元素都不可见，但是这两个选项是有区别的:</p><p>1、v-if在条件切换时，会对标签进行适当的创建和销毁，而v-show则仅在初始化时加载一次，因此v-if的开销相对来说会比v-show大。</p><p>2、v-if是惰性的，只有当条件为真时才会真正渲染标签；如果初始条件不为真，则v-if不会去渲染标签。v-show则无论初始条件是否成立，都会渲染标签，它仅仅做的只是简单的CSS切换。</p><h3><span id="computed和watch的区别"><strong>computed和watch的区别</strong></span></h3><h4><span id="计算属性computed">计算属性computed：</span></h4><ol><li>支持缓存，只有依赖数据发生改变，才会重新进行计算</li><li>不支持异步，当computed内有异步操作时无效，无法监听数据的变化</li><li>computed 属性值会默认走缓存，计算属性是基于它们的响应式依赖进行缓存的，也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值</li><li>如果一个属性是由其他属性计算而来的，这个属性依赖其他属性，是一个多对一或者一对一，一般用computed</li><li>如果computed属性属性值是函数，那么默认会走get方法；函数的返回值就是属性的属性值；在computed中的，属性都有一个get和一个set方法，当数据变化时，调用set方法。</li></ol><h4><span id="侦听属性watch">侦听属性watch：</span></h4><ol><li>不支持缓存，数据变，直接会触发相应的操作；</li><li>watch支持异步；</li><li>监听的函数接收两个参数，第一个参数是最新的值；第二个参数是输入之前的值；</li><li>当一个属性发生变化时，需要执行对应的操作；一对多；</li><li>监听数据必须是data中声明过或者父组件传递过来的props中的数据，当数据变化时，触发其他操作。</li></ol><h3><span id="v-for-key的作用">v-for key的作用</span></h3><p>当Vue用 v-for 正在更新已渲染过的元素列表时，它默认用“就地复用”策略。如果数据项的顺序被改变，Vue将不是移动DOM元素来匹配数据项的改变，而是简单复用此处每个元素，并且确保它在特定索引下显示已被渲染过的每个元素。</p><p>为了给Vue一个提示，以便它能跟踪每个节点的身份，从而重用和重新排序现有元素，你需要为每项提供一个唯一 key 属性。key属性的类型只能为 string或者number类型。</p><p>key 的特殊属性主要用在Vue的虚拟DOM算法，在新旧nodes对比时辨识VNodes。如果不使用 key，Vue会使用一种最大限度减少动态元素并且尽可能的尝试修复/再利用相同类型元素的算法。使用key，它会基于key的变化重新排列元素顺序，并且会移除 key 不存在的元素。</p><h3><span id="vue如何监听对象或者数组某个属性的变化"><strong>vue如何监听对象或者数组某个属性的变化</strong></span></h3><p>当在项目中直接设置数组的某一项的值，或者直接设置对象的某个属性值，这个时候，你会发现页面并没有更新。这是因为Object.defineProperty()限制，监听不到变化。<strong>vue3使用proxy则不存在此问题</strong>。</p><p>解决方式：</p><ul><li><p>this.$set(你要改变的数组/对象，你要改变的位置/key，你要改成什么value)：</p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">this</span>.$set(<span class="built_in">this</span>.arr, <span class="number">0</span>, <span class="string">&quot;OBKoro1&quot;</span>); <span class="comment">// 改变数组</span></span><br><span class="line"><span class="built_in">this</span>.$set(<span class="built_in">this</span>.obj, <span class="string">&quot;c&quot;</span>, <span class="string">&quot;OBKoro1&quot;</span>); <span class="comment">// 改变对象</span></span><br></pre></td></tr></table></figure></li><li><p>调用以下几个数组的方法</p></li></ul><figure class="highlight isbl"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">splice</span>()、 <span class="title">push</span>()、<span class="title">pop</span>()、<span class="title">shift</span>()、<span class="title">unshift</span>()、<span class="title">sort</span>()、<span class="title">reverse</span>()</span></span><br></pre></td></tr></table></figure><p>vue源码里缓存了array的原型链，然后重写了这几个方法，触发这几个方法的时候会observer数据，意思是使用这些方法不用我们再进行额外的操作，视图自动进行更新。 推荐使用splice方法会比较好自定义,因为splice可以在数组的任何位置进行删除/添加操作</p><h3><span id="vue如何获取dom"><strong>vue如何获取dom</strong></span></h3><p>和React相似，先给标签设置一个ref值，再通过this.$refs.domName获取，例如：</p><figure class="highlight javascript"><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">&lt;div ref=<span class="string">&quot;test&quot;</span>&gt;&lt;/div&gt;</span><br><span class="line"></span><br><span class="line"><span class="keyword">const</span> dom = <span class="built_in">this</span>.$refs.test</span><br></pre></td></tr></table></figure><h1><span id="优化建议">优化建议</span></h1><ol><li><h3><span id="v-if-和-v-show-区分使用场景">v-if 和 v-show 区分使用场景</span></h3><p><strong>v-if</strong> 是 <strong>真正</strong> 的条件渲染，因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建；也是<strong>惰性的</strong>：如果在初始渲染时条件为假，则什么也不做——直到条件第一次变为真时，才会开始渲染条件块。</p><p><strong>v-show</strong> 就简单得多， 不管初始条件是什么，元素总是会被渲染，并且只是简单地基于 CSS 的 display 属性进行切换。</p><p>所以，v-if 适用于在运行时很少改变条件，不需要频繁切换条件的场景；v-show 则适用于需要非常频繁切换条件的场景。</p></li><li><h3><span id="computed-和-watch-区分使用场景">computed 和 watch 区分使用场景</span></h3><p><strong>computed：</strong> 是计算属性，依赖其它属性值，并且 computed 的值有缓存，只有它依赖的属性值发生改变，下一次获取 computed 的值时才会重新计算 computed  的值；</p><p><strong>watch：</strong> 更多的是「观察」的作用，类似于某些数据的监听回调 ，每当监听的数据变化时都会执行回调进行后续操作；</p><p><strong>运用场景：</strong></p><ul><li>当我们需要进行数值计算，并且依赖于其它数据时，应该使用 computed，因为可以利用 computed 的缓存特性，避免每次获取值时，都要重新计算；</li><li>当我们需要在数据变化时执行异步或开销较大的操作时，应该使用 watch，使用 watch 选项允许我们执行异步操作 ( 访问一个 API )，限制我们执行该操作的频率，并在我们得到最终结果前，设置中间状态。这些都是计算属性无法做到的。</li></ul></li><li><h3><span id="v-for-遍历必须为-item-添加-key且避免同时使用-v-if">v-for 遍历必须为 item 添加 key，且避免同时使用 v-if</span></h3><p>v-for 比 v-if 优先级高，如果每一次都需要遍历整个数组，将会影响速度，尤其是当之需要渲染很小一部分的时候，必要情况下应该替换成 computed 属性。</p></li><li><h3><span id="事件的销毁">事件的销毁</span></h3><p>Vue 组件销毁时，会自动清理它与其它实例的连接，解绑它的全部指令及事件监听器，但是仅限于组件本身的事件。 如果在 js 内使用 addEventListene 等方式是不会自动销毁的，我们需要在组件销毁时手动移除这些事件的监听，以免造成内存泄露，如：</p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="title">created</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">  addEventListener(<span class="string">&#x27;click&#x27;</span>, <span class="built_in">this</span>.click, <span class="literal">false</span>)</span><br><span class="line">&#125;,</span><br><span class="line"><span class="function"><span class="title">beforeDestroy</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">  removeEventListener(<span class="string">&#x27;click&#x27;</span>, <span class="built_in">this</span>.click, <span class="literal">false</span>)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li><li><h3><span id="服务端渲染-ssr-or-预渲染">服务端渲染 SSR or 预渲染</span></h3></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;之前公司用的都是Vue，最近在新公司使用的是React。基于自己5个月来使用React的一些感受，把React 和 Vue做了一个简单的对比。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Vue 组件：&lt;/strong&gt;&lt;/p&gt;
&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;24&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;25&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;26&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;27&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;28&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;29&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;30&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;31&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;32&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;33&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;34&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;35&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;36&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;37&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;38&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;39&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;40&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;41&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&amp;lt;template&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;  &lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;div&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;class&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&amp;quot;app&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;name&quot;&gt;div&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;lt;/template&amp;gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;export&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;default&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &lt;span class=&quot;attr&quot;&gt;components&lt;/span&gt;: &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &amp;#125;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &lt;span class=&quot;attr&quot;&gt;props&lt;/span&gt;: &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &amp;#125;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  data () &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &amp;#125;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &lt;span class=&quot;attr&quot;&gt;computed&lt;/span&gt;: &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &amp;#125;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &lt;span class=&quot;attr&quot;&gt;watch&lt;/span&gt;: &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &amp;#125;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  created () &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &amp;#125;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  mounted () &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &amp;#125;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &lt;span class=&quot;attr&quot;&gt;methods&lt;/span&gt;: &amp;#123;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;  &amp;#125;,&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&amp;#125;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;javascript&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;name&quot;&gt;script&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;&lt;span class=&quot;name&quot;&gt;style&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;scoped&lt;/span&gt; &lt;span class=&quot;attr&quot;&gt;lang&lt;/span&gt;=&lt;span class=&quot;string&quot;&gt;&amp;quot;scss&amp;quot;&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;xml&quot;&gt;&lt;span class=&quot;tag&quot;&gt;&amp;lt;/&lt;span class=&quot;name&quot;&gt;style&lt;/span&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="javascript" scheme="http://landerqi.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>VueJs框架理解</title>
    <link href="http://landerqi.com/2020/11/12/VueJs%E6%A1%86%E6%9E%B6%E7%90%86%E8%A7%A3/"/>
    <id>http://landerqi.com/2020/11/12/VueJs框架理解/</id>
    <published>2020-11-12T02:48:53.000Z</published>
    <updated>2020-12-31T09:51:48.586Z</updated>
    
    <content type="html"><![CDATA[<p>使用Vue已经5年有余了，每次看Vue相关的知识点都有新的收获。果然，在学习的过程中还是得多总结，总结过程中可以查漏补缺，还能加强记忆。</p><span id="more"></span><!-- toc --><ul><li><a href="#vue">vue</a></li></ul><!-- tocstop --><h3><span id="vue">vue</span></h3><p>Vue是一套用于构建用户界面的渐进式MVVM框架，渐进式即</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;使用Vue已经5年有余了，每次看Vue相关的知识点都有新的收获。果然，在学习的过程中还是得多总结，总结过程中可以查漏补缺，还能加强记忆。&lt;/p&gt;
    
    </summary>
    
    
      <category term="javascript" scheme="http://landerqi.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>人性的弱点</title>
    <link href="http://landerqi.com/2019/10/28/%E4%BA%BA%E6%80%A7%E7%9A%84%E5%BC%B1%E7%82%B9/"/>
    <id>http://landerqi.com/2019/10/28/人性的弱点/</id>
    <published>2019-10-28T03:24:01.000Z</published>
    <updated>2019-10-28T03:27:23.917Z</updated>
    
    <content type="html"><![CDATA[<h6><span id="戴尔卡耐基33个笔记">戴尔·卡耐基，33个笔记</span></h6><h3><span id="我要喜欢你">我要喜欢你</span></h3><blockquote><p>朋友的这番话，改变了我对演讲的整个看法。现在，每当我准备发表演讲的时候，都会在事前先静心祷告：“神啊，求你帮助我传达出对这些听众有益的信息来，让他们有所收获，满心欢喜地回家。”这样的祷告对我十分有用，而我也的确希望能对听众有帮助。这样的祷告使我谦卑地体会到自己只不过是个传达某些信息的演讲员，而不是要显露自己的学问或风采。我的目的是要带给听众一些鼓舞性的思想，以期对他们的生活有助益。</p></blockquote><span id="more"></span><h3><span id="如要采蜜不可弄翻蜂巢">如要采蜜，不可弄翻蜂巢</span></h3><blockquote><p>让我们记住：我们所相处的对象，并不是绝对理性的动物，而是充满了情绪变化、成见、自负和虚荣的东西。</p></blockquote><blockquote><p>本杰明·富兰克林年轻的时候并不圆滑，但后来却变得富有外交手腕，善与人应对，因而成了美国驻法大使。他的成功秘诀是：“我不说别人的坏话，只说大家的好处。”</p></blockquote><blockquote><p>善解人意和宽恕他人，需要修养和自制的功夫。</p></blockquote><h3><span id="莫与小人较劲">莫与小人较劲</span></h3><blockquote><p>面对这种自以为口才很好，却令人讨厌的人时，你既不要随便示弱，也无须自我降格，跟他针锋相对。<strong>你应该这样做</strong>：</p></blockquote><ul><li>在对方说得起劲，更难听的话也冲口而出的时候，你实在不必再忍受这样肤浅的人，你可以站起来礼貌地说：“对不起，请继续你的演说。我先走了。”如果对方还有一点自尊的话，他应该感到羞耻。</li><li>当他正在心情兴奋地把你的弱点一一挑出来取笑时，你只须平静地定睛看着他，像一个旁观者，兴味盎然地欣赏眼前这个小丑每一个表情，对方便会难以再唱独角戏。</li><li>当他实在太惹人讨厌，总是找你的麻烦，每句话都是针对着你时，你要尽量抑制怒气，装听不见，切勿中了对方的诡计，跟他唇枪舌剑。如果你根本不理会他，他便无法再独白下去，他的弱点会因此而暴露无遗，有目共睹，同时显出你的涵养，非比寻常。</li></ul><blockquote><p>在公共场合里，我们时常会遇到一些不受欢迎的人物。例如，在电影院里，年轻人忘情地大叫大笑，高谈阔论；在音乐会中，邻座的观众不停地讲话，令你十分苦恼，你想出声请他们安静下来，却碍于礼貌，不愿当众指责对方，只有强自忍受。这样，你会变得越来越内向怕事，不敢据理力争，凡事得过且过。<br>    你不要欺负人，也不可随便让别人踩到你的头上，这才是正确的人生观。</p></blockquote><blockquote><p>培养说话技巧，在不伤害他人自尊心的情况下，达到你心目中的效果，何乐而不为？一个人在愤怒的时候，他的言行通常会出错，无论何时何地，你必须切记这一点。<br>    把你的敌人化为朋友，才是最高明的做法。<br>    该告别时就告别</p></blockquote><h3><span id="仪表是你的门面">仪表是你的门面</span></h3><blockquote><p>柜台后面是什么样，车间里很可能也就是什么样。时髦的女售货员一定很讲究穿着，她会厌恶肮脏的衣领、磨破的袖口和皱巴巴的领带，难道不是吗？事实上，关注个人习惯和整体仪表，就会对邋遢散漫的习惯产生警觉。”</p></blockquote><ol><li>三点一线：一个衣冠楚楚的男人，他的衬衫领口、皮带袢和裤子前开口外侧应该在一条线上。</li><li>说到皮带袢，如果你系领带，领带尖可千万不要触到皮带袢上哟！</li><li>除非你是在解领带，否则无论何时何地松开领带结都是很不礼貌的。</li><li>一身漂亮的西服和领带会使一个男人看上去非常时髦，而一套好西装却不系领带，会使他看着更时髦。</li><li>如果你穿西装，但不系领带，就可以穿那种便鞋，如果你系了领带，就绝对不可以了。</li><li>新买的衬衫，如果你能在脖子和领子之间插进两个手指，就说明这件衬衫洗过之后仍然会很适合。</li><li>透过男人的衬衫能隐隐约约看到穿在里面的T恤，就有如女人穿着能透出里面内裤的裤子一样尴尬。</li><li>如果不是专业的手洗，一件300多元的衬衫很快就会只值25元。</li><li>精神的发型、一双好鞋，胜过一套昂贵的西装。</li><li>一双90元的鞋的寿命应该是180元一双的鞋的一半，而1000元一双的鞋将伴你一生。</li><li>如果你穿的是3粒扣西装，可以只系第一颗纽扣，也可以系上面两颗纽扣，就是不能只系最下面一颗，而将上面两颗扣子敞开着。</li><li>穿双排扣西装所有的扣子一个也不能不扣，特别是领口的扣子。</li><li>如果你去某个场合拿不准穿什么服装，那么隆重点儿远比随便点儿强得多，人们会认为你随后还要去一个更重要的场合呢！</li><li>一件便宜的羊绒衫实际上远远没有一件好一点儿的羊毛衫更舒服。</li><li>除非你是橄榄球运动员，否则就不要把任何与名字有关的字母或号码穿在身上。</li><li>45岁以下的你请不要过早地叼上烟斗，也不要戴那种浅圆的小帽。</li><li>比穿没盖过踝骨的袜子更糟糕的是穿没盖过踝骨的格子袜子。</li><li>配正装一定不要穿白色的袜子。</li><li>无论如何，你不必有太多卡其布休闲装、白色的纯棉T恤或厚棉布网球鞋，毕竟一周只有一个星期六。</li><li>穿衣服的第一常规就是打破一切常规——包括我们上面所说的一切。<br>我强调衣着的重要性，但并不是要你像英国花花公子博·布鲁梅尔那样，一年仅做衣服就花4000美元，扎一个领结也要花上几个小时。过分注重穿着甚至比完全忽视还要糟糕。那些像博·布鲁梅尔那样的人太讲究穿着了，他们一门心思地扑在对衣着的研究上，而忽略了内心修养和神圣的责任。在我看来，穿衣应该与身份相称，这既是一种责任，也是最实际的节俭。</li></ol><h3><span id="练就关照他人而不造作的功夫">练就关照他人而不造作的功夫</span></h3><blockquote><p>1.称赞对方希望被称赞的事物</p></blockquote><blockquote><p>2.偶尔的佯装，实属必要</p></blockquote><blockquote><p>3.背地里称赞，最令人高兴</p></blockquote><h3><span id="谈论他的兴趣所在">谈论他的兴趣所在</span></h3><blockquote><p>每一个与西奥多·罗斯福交谈过的人，都对他渊博的知识感到惊讶。哥马利尔·布雷佛这样写道：“无论是一名牛仔还是骑兵，纽约政客还是外交官，罗斯福都知道该对他说什么话。”他是怎么办到的呢？原来，每当有人来访的前一天晚上，罗斯福就开夜车，翻读这位客人特别感兴趣的东西。因为罗斯福知道，打动人心的最佳方式是：跟他谈论他最感兴趣的事物。</p></blockquote><h3><span id="第四章-交谈如何更愉快">第四章 交谈如何更愉快</span></h3><blockquote><p>让别人有发表意见的机会，做一个善于倾听的人，那么你一定会大受欢迎。</p></blockquote><h3><span id="十之八九你赢不了争论">十之八九，你赢不了争论</span></h3><blockquote><p>十之八九，你赢不了争论</p></blockquote><blockquote><p>永远避免跟人家正面冲突。<br>天底下只有一种能在争论中获胜的方式，那就是避免争论。避免争论，要像你避免响尾蛇和地震那样。</p></blockquote><h3><span id="提升财商">提升财商</span></h3><blockquote><p>财商包括两方面的能力：一是正确认识金钱及金钱规律的能力；二是正确使用金钱及金钱规律的能力。</p></blockquote><h3><span id="树立正确的工作态度">树立正确的工作态度</span></h3><blockquote><p>人往往就是在克服困难的过程中，产生了勇气、坚毅和高尚的品格。常常抱怨工作的人，终其一生，绝不会有真正的成功。抱怨和推诿，其实是懦弱的自白。</p></blockquote><h3><span id="比薪水更宝贵的">比薪水更宝贵的</span></h3><blockquote><p>你的雇主可以控制你的工资，可是他却无法遮住你的眼睛，捂上你的耳朵，阻止你去思考、去学习。换句话说，他无法阻止你为将来所做的努力，也无法剥夺你因此而得到的回报。</p></blockquote><h3><span id="不要试图改造对方">不要试图改造对方</span></h3><blockquote><p>正如詹姆士所说的：“与人交往，第一件应学的事情就是不要干涉他们自己快乐的特殊方法，如果那些方法与我们不相冲突的话。”如果你要你的家庭生活快乐，第二项原则是：不要试图改造你的配偶。<br>去适应，而不是改造你的配偶。</p></blockquote><h3><span id="从改善最坏的情况开始">从改善最坏的情况开始</span></h3><blockquote><p>如果你有担忧的问题，就做到下面<strong>三件事情</strong>：</p></blockquote><p>一、问你自己：“可能发生的最坏的情况是什么？”</p><p>二、如果你必须接受的话，就准备接受它。</p><p>三、然后镇定地想办法改善最坏的情况。</p><h3><span id="避免落入杞人忧天的状况">避免落入杞人忧天的状况</span></h3><blockquote><p>最重要的就是不要去看远方模糊的，而要做手边清楚的事。</p></blockquote><h3><span id="养成良好的工作习惯">养成良好的工作习惯</span></h3><blockquote><p>良好的工作习惯之一：清除你桌上所有的纸张，只留下与你正要处理的问题有关的东西。</p></blockquote><blockquote><p>良好的工作习惯之二：做事分清轻重缓急。</p></blockquote><blockquote><p>良好的工作习惯之三：当你碰到问题时，如果必须做决定，就当场解决，不要迟疑不决。</p></blockquote><blockquote><p>良好的工作习惯之四：学会如何组织、分层负责和监督。</p></blockquote><h3><span id="第九章-保持充沛的精力">第九章 保持充沛的精力</span></h3><blockquote><p>防止疲劳的规则是：经常休息，在你感到疲倦以前就休息。</p></blockquote><h3><span id="第十章-踏上轻松快乐之旅">第十章 踏上轻松快乐之旅</span></h3><blockquote><p>我们只有学会了放弃，才会拥有一份成熟，才会活得更加充实、坦然和轻松。</p></blockquote><h3><span id="演奏你自己的乐器">演奏你自己的乐器</span></h3><blockquote><p>下面是一位已故的诗人道格拉斯·马罗区所说的：</p></blockquote><p>假如你不能成为山顶的一棵青松，</p><p>就做一棵小树生长在山谷中，</p><p>但须是溪边最好的一小棵。</p><p>假如你不能成为一棵大树，</p><p>就做一丛灌木。</p><p>假如你不能成为一丛灌木，</p><p>就做一片绿草让公路上也有几分欢娱颜色。</p><p>假如你不能成为一只麝香鹿，</p><p>就做一条鲈鱼，</p><p>但须做湖里最好的一条鱼。</p><p>我们不能都做船长，</p><p>我们得做船员。</p><p>世上的事情，多得做不完，</p><p>工作有大的，也有小的。</p><p>我们该做的工作，就在你的手边。</p><p>假如你不能做一条公路，</p><p>就做一条小径。</p><p>假如你不能做太阳，</p><p>就做一颗星星。</p><p>不能凭大小来断定你的输赢，</p><p>无论你做什么都要做最好的一名。</p><p>不要模仿别人，让我们找到自己，保持本色。</p><h3><span id="拿自己开开玩笑">拿自己开开玩笑</span></h3><blockquote><p>与其愤世嫉俗地自怨自艾，何不谈笑风生地自我解嘲。</p></blockquote><h3><span id="不要期望他人的感恩">不要期望他人的感恩</span></h3><blockquote><p>我的重点是：他指望别人感恩乃是一项一般性的错误，他实在不了解人性。</p></blockquote><h3><span id="从做愚人开始">从做愚人开始</span></h3><blockquote><p>豪威尔的这种做法可能是向富兰克林学来的。不过富兰克林并不等到周末，他每晚都自我反省。他发现过十三项严重的错误。其中三项是：浪费时间、关心琐事及与人争论。睿智的富兰克林知道，不改正这些缺点，是成不了大业的。所以，他一周定一个要改进的缺点做目标，并每天记录赢的是哪一边。下一周，他再努力改进另一个坏习惯，他一直与自己的缺点奋战，整整持续了两年。</p></blockquote><h3><span id="对不公正的批评报之一笑">对不公正的批评——报之一笑</span></h3><blockquote><p>当你成为不公正批评的受害者时，这个座右铭尤其管用。别人骂你的时候，你可以回骂他，可是对那些“只笑一笑”的人，你能说什么呢？</p></blockquote><h3><span id="多做阻抗训练">多做阻抗训练</span></h3><blockquote><p>恐惧、自我设限及接受失败，最后只会像莎士比亚所说的使你“困在沙洲和痛苦之中”，但是你可以借着信心、积极的心态和明确的目标来克服这些消极心态。</p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;h6 id=&quot;戴尔·卡耐基，33个笔记&quot;&gt;&lt;a href=&quot;#戴尔·卡耐基，33个笔记&quot; class=&quot;headerlink&quot; title=&quot;戴尔·卡耐基，33个笔记&quot;&gt;&lt;/a&gt;戴尔·卡耐基，33个笔记&lt;/h6&gt;&lt;h3 id=&quot;我要喜欢你&quot;&gt;&lt;a href=&quot;#我要喜欢你&quot; class=&quot;headerlink&quot; title=&quot;我要喜欢你&quot;&gt;&lt;/a&gt;我要喜欢你&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;朋友的这番话，改变了我对演讲的整个看法。现在，每当我准备发表演讲的时候，都会在事前先静心祷告：“神啊，求你帮助我传达出对这些听众有益的信息来，让他们有所收获，满心欢喜地回家。”这样的祷告对我十分有用，而我也的确希望能对听众有帮助。这样的祷告使我谦卑地体会到自己只不过是个传达某些信息的演讲员，而不是要显露自己的学问或风采。我的目的是要带给听众一些鼓舞性的思想，以期对他们的生活有助益。&lt;/p&gt;
&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="读书笔记" scheme="http://landerqi.com/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>css文本自动至右向左排</title>
    <link href="http://landerqi.com/2019/08/26/css%E6%96%87%E6%9C%AC%E8%87%AA%E5%8A%A8%E8%87%B3%E5%8F%B3%E5%90%91%E5%B7%A6%E6%8E%92/"/>
    <id>http://landerqi.com/2019/08/26/css文本自动至右向左排/</id>
    <published>2019-08-26T06:35:25.000Z</published>
    <updated>2019-08-26T09:25:10.332Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="问题描述">问题描述：</span></h3><p>测试发现特殊字符，会导致页面布局混乱。当一组并列的span标签，第一个标签里面是特殊字符（并且还要第一个字符是阿拉伯语，希伯来语）的时候，导致这几个所有<code>span</code>标签的文本全默认自右向左排了。</p><p>这样就会出现一个明显的bug：我设置的几个<code>text-overflow</code>的省略三个点出现在了左边, 就像这样:</p><img src="https://fesystem.bs2dl.yy.com/1566811454453508" width="567"><span id="more"></span><p>如上图，我把我的昵称改成了特殊字符，结果发现yy客户端的聊天窗口也出现了同样的问题！我发现事情可能并不简单！</p><p><strong>出问题的html代码结构如下：</strong><br><img src="https://fesystem.bs2dl.yy.com/1566809192230131" width="660"></p><p>我试着把<code>overflow: hidden</code>去掉，果然文字从左边超出了天际：<br><img src="https://fesystem.bs2dl.yy.com/15668090377317" width="460"></p><h3><span id="解决思路">解决思路：</span></h3><ol><li><p>最开始以为是自己的代码问题，各种修改样式，发现完全没效果。</p></li><li><p><code>تヅツッシÜϡ</code>， 尝试各种修改代码无果之后，我就想试试是不是这个字符串的问题。然后我就一个一个删，最后还真发现，<strong>删了第一个的时候，恢复正常了</strong>。确定了是第一个字符影响了。</p></li><li><p>直接复制第一个字符google， 发现这是阿拉伯字符。</p></li><li><p>搜索阿拉伯字符，发现是一些阿拉伯语，希伯来语会默认自右向左排，所以导致了，我后面几个同级的标签全部自右向左了。</p></li><li><p>哈哈，问题定位到了就好解决了，试了下在html中加 dir=”ltr”属性，依然无效。</p></li><li><p>之后试了给外层标签设置：<code>writing-mode</code>，因为在<code>cef(一种pc客户端内嵌h5网页的技术，其使用的是chrome内核)</code>里面，他的chrome内核才是49版本，所以这个属性的值很少(属性值并不全)，设置一遍之后，发现没有生效:</p> <img src="https://fesystem.bs2dl.yy.com/156681011102544" width="660"></li><li><p>所以新建了一个测试页面，在chrome中调试，发现<code>writing-mode</code>的所有属性都无效。</p></li><li><p>所有都无效，<strong>差点放弃</strong>，最后在select框的div标签中加了<strong>dir=”ltr”属性，生效了！因为cef中不支持原生option选择框，所以我这里的选择框是异步生成的，导致在html中的 dir=”ltr”属性无效！到此终于解决了这个问题:</strong></p> <img src="https://fesystem.bs2dl.yy.com/1566810177849451" width="660"></li></ol><p><strong>一波三折，终于解决了，也多亏了公司测试同事可以测出这个问题，在国内确实挺难发现这个问题，因为大家不认识阿拉伯字符，很多人第一感觉就当乱码处理了。而这个bug的出现又必须是阿拉伯字符，并且还一定是要在最前面，最好后面还得跟上几个并列的标签（里面有一大串文字），这样视觉上一看就是个bug， 把bug效果放大了。</strong></p><p><strong>后来想起来，之前一个新加坡的前端来公司做过一个分享，就是关于css文字方向的！这个问题确实有趣，解决的过程也相当有意思，故写个blog记录一下。</strong></p>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;问题描述：&quot;&gt;&lt;a href=&quot;#问题描述：&quot; class=&quot;headerlink&quot; title=&quot;问题描述：&quot;&gt;&lt;/a&gt;问题描述：&lt;/h3&gt;&lt;p&gt;测试发现特殊字符，会导致页面布局混乱。当一组并列的span标签，第一个标签里面是特殊字符（并且还要第一个字符是阿拉伯语，希伯来语）的时候，导致这几个所有&lt;code&gt;span&lt;/code&gt;标签的文本全默认自右向左排了。&lt;/p&gt;
&lt;p&gt;这样就会出现一个明显的bug：我设置的几个&lt;code&gt;text-overflow&lt;/code&gt;的省略三个点出现在了左边, 就像这样:&lt;/p&gt;
&lt;img src=&quot;https://fesystem.bs2dl.yy.com/1566811454453508&quot; width=&quot;567&quot;&gt;
    
    </summary>
    
    
      <category term="解决问题" scheme="http://landerqi.com/tags/%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98/"/>
    
      <category term="css3" scheme="http://landerqi.com/tags/css3/"/>
    
  </entry>
  
  <entry>
    <title>mongodb update数据updatedAt时间不更新问题</title>
    <link href="http://landerqi.com/2019/08/12/mongodb-update%E6%95%B0%E6%8D%AEupdatedAt%E6%97%B6%E9%97%B4%E4%B8%8D%E6%9B%B4%E6%96%B0%E9%97%AE%E9%A2%98/"/>
    <id>http://landerqi.com/2019/08/12/mongodb-update数据updatedAt时间不更新问题/</id>
    <published>2019-08-12T11:05:47.000Z</published>
    <updated>2019-08-12T11:41:15.090Z</updated>
    
    <content type="html"><![CDATA[<p>今天在写一个koa项目的时候，需要操作mongoDB修改数据，参考之前一些旧项目的代码，他是这样update数据的：</p><img src="https://fesystem.bs2dl.yy.com/156560781156486" alt><p>直接把要更新的数据传入进去，这样数据也是可以更新成功，但是会有一个问题，<code>updateAt</code> 的<code>timestamps</code>永远不会更新（因为我需要用到这个时间来做展示）:</p><span id="more"></span><img src="https://fesystem.bs2dl.yy.com/1565607692818579" alt><p>Google之后发现很多解释都不是针对这个问题的。我又换了<code>save()</code>, <code>findOneAndUpdate()</code>等方法，发现还是有这个问题。</p><p><strong>解决办法：</strong><br>我把这个update方法重写了一下：<br><img src="https://fesystem.bs2dl.yy.com/1565608416665389" alt><br><strong>发现竟然可以了！</strong></p><p>其实我本来是想用javascript的__展开语法(Spread syntax)__重写<code>updateTime</code>这个值的，结果误打误撞的解决了这个问题:</p><figure class="highlight javascript"><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"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 根据_id lib</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">&#123;string&#125;</span> </span>data lib数据结构</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return <span class="type">&#123;object&#125;</span> </span>返回更新结果&#123; n: 1, nModified: 1, ok: 1 &#125;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">update (data) &#123;</span><br><span class="line">  <span class="keyword">return</span> libs.findOneAndUpdate(&#123; <span class="attr">_id</span>: data._id &#125;, &#123; <span class="attr">$set</span>: &#123;...data, ...&#123; <span class="attr">updateTime</span>: <span class="built_in">Date</span>.now() &#125; &#125; &#125;)</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>虽然这种方法也可以正常更新<code>updateTime</code>, 但是当我发现是因为缺少<code>$set</code>更新操作符后，就觉得没有必要再多此一举重写<code>updateTime</code>了。</p><p>之后我又去仔细看了一下文档，里面确实有写这个<code>$set</code> 更新操作符（Update Operators）是必须的：<br><img src="https://fesystem.bs2dl.yy.com/1565607759715446" alt></p><p><strong>Update Operators:</strong><br><img src="https://fesystem.bs2dl.yy.com/1565607787959236" alt="Update Operators"></p><p>总结发现果然文档才是最好的学习资料，借鉴一些旧项目可以快速上手，但是如果想到对所用到的技术有更深的理解的话，还是需要仔细阅读官方文档才行。之前参考的旧项目也是前端同事写的，前端同事接触数据库较少，代码中存在问题的可能性大，所以不要盲目的复制、粘贴。</p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;今天在写一个koa项目的时候，需要操作mongoDB修改数据，参考之前一些旧项目的代码，他是这样update数据的：&lt;/p&gt;
&lt;img src=&quot;https://fesystem.bs2dl.yy.com/156560781156486&quot; alt=&quot;&quot;&gt;

&lt;p&gt;直接把要更新的数据传入进去，这样数据也是可以更新成功，但是会有一个问题，&lt;code&gt;updateAt&lt;/code&gt; 的&lt;code&gt;timestamps&lt;/code&gt;永远不会更新（因为我需要用到这个时间来做展示）:&lt;/p&gt;
    
    </summary>
    
    
      <category term="解决问题" scheme="http://landerqi.com/tags/%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98/"/>
    
      <category term="数据库" scheme="http://landerqi.com/tags/%E6%95%B0%E6%8D%AE%E5%BA%93/"/>
    
  </entry>
  
  <entry>
    <title>卓有成效的管理者</title>
    <link href="http://landerqi.com/2019/08/12/%E5%8D%93%E6%9C%89%E6%88%90%E6%95%88%E7%9A%84%E7%AE%A1%E7%90%86%E8%80%85/"/>
    <id>http://landerqi.com/2019/08/12/卓有成效的管理者/</id>
    <published>2019-08-12T07:01:43.000Z</published>
    <updated>2019-08-12T07:05:00.732Z</updated>
    
    <content type="html"><![CDATA[<p>很早之前老师就推荐我们阅读管理大师德鲁克的书，但是因为自己对这方面的书籍兴趣不大，所以一直没有去找来看。直到最近空闲时间比较多，我才看完了彼得·德鲁克的《卓有成效的管理者》，受益匪浅。</p><p>彼得·德鲁克曾任美国通用汽车公司、克莱斯勒公司、IBM公司等大企业的管理顾问，管理学是他一生主要的研究对象。此书是彼得·德鲁克40多年前写的一本著作，但是书中的思想和观点，现在读起来也仍然让人感到那么实际有效，感觉对自己的学习甚至是整个的人生规划都具有非常重要的指导意义。</p><p>《卓有成效的管理者》这本书告诉我，一个优秀的管理者首先是自己的管理者。将自己有效管理起来，然后才能进一步去影响、指导他人。管理者在内心上和实际工作中的有效性训练很重要，要有一种倾向性的意识去自我提高，发展自己的有效性，这样才能成为一名真正的卓有成效的管理者。</p><p>最后我想说，无论是否是管理者，都能从这本书里得到启发，因为管理自己也很重要。这本书的内容不多，但是干货非常多，我在里面划的笔记有87处之多。</p><span id="more"></span><hr><h3><span id="笔记摘录">笔记摘录</span></h3><p>◆ 推荐序一</p><blockquote><p>在美国克莱蒙特大学附近，有一座小小的德鲁克纪念馆，走进这座用他的故居改成的纪念馆，正对客厅入口的显眼处有一段他的名言：在一个由多元的组织所构成的社会中，使我们的各种组织机构负责任地、独立自治地、高绩效地运作，是自由和尊严的唯一保障。有绩效的、负责任的管理是对抗和替代极权专制的唯一选择。</p></blockquote><blockquote><p>要了解德鲁克的经历怎样影响了他的信念和价值观，最好去读他的《旁观者》；要弄清什么是极权主义和为什么大众会拥护它，可以去读汉娜·阿伦特1951年出版的《极权主义的起源》。</p></blockquote><blockquote><p>1999年1月18日，德鲁克接近90岁高龄，在回答“我最重要的贡献是什么”这个问题时，他写了下面这段话：我着眼于人和权力、价值观、结构和规范去研究管理学，而在所有这些之上，我聚焦于“责任”，那意味着我是把管理学当作一门真正的“博雅技艺”来看待的。</p></blockquote><blockquote><p>除了让组织取得绩效和成果，管理者还有没有其他的责任？或者换一种说法，绩效和成果仅限于可量化的经济成果和财富吗？对一个工商企业来说，除了为客户提供价廉物美的产品和服务、为股东赚取合理的利润，能否同时成为一个良好的、负责任的“社会公民”，能否同时帮助自己的员工在品格和能力两方面都得到提升呢？这似乎是一个太过苛刻的要求，但它是一个合理的要求。</p></blockquote><p>◆ 谁是管理者</p><blockquote><p>在一个现代的组织里，如果一位知识工作者能够凭借其职位和知识，对该组织负有贡献的责任，因而能对该组织的经营能力及达成的成果产生实质性的影响，那么他就是一位管理者。</p></blockquote><p>◆ 管理者必须面对的现实</p><blockquote><p>（1）管理者的时间往往只属于别人，不属于自己。</p></blockquote><blockquote><p>（2）管理者往往被迫忙于“日常运作”，除非他们敢于采取行动来改变周围的一切。</p></blockquote><blockquote><p>（3）使管理者缺乏有效性的第三项现实因素，是管理者本身处于一个“组织”之中。</p></blockquote><blockquote><p>（4）最后，管理者身处一个组织的“内部”，受到组织的局限。</p></blockquote><blockquote><p>真正的问题是，外部情况往往是质的性质，难以量化，它们还不能被称为事实。所谓事实，应该是已经认定，已做分类，并且已确知其关联性。在我们对事实进行量化之前，必须先掌握一个概念，那就是：必须先从无数现象中抽象出某一具体的特性，并对其命名，然后才能进行计算。</p></blockquote><blockquote><p>对于外部的情况，真正重要的不是趋势，而是趋势的转变。趋势的转变才是决定一个机构及其努力的成败关键。对这种转变，必须要有所觉察，转变是无法计量、无法界定、无法分类的。</p></blockquote><p>◆ 对有效性的认识</p><blockquote><p>考虑到组织的需要，有效性应该受到优先的重视。同时，有效性也是管理者达成目标和绩效的必要手段，因此更应该受到高度优先的重视。</p></blockquote><p>◆ 卓有成效可以学会吗</p><blockquote><p>我认识许多有效的管理者，他们脾气不同、能力也不同；他们所做的事不同，做事的方法也不同；他们的个性、知识和志趣，也各不相同。事实上，他们几乎在每一方面都各自不同，却有一项共同点：人人都具有做好该做的事情的能力。</p></blockquote><blockquote><p>下列5项是要成为一个卓有成效的管理者，必须在思想上养成的习惯。（1）有效的管理者知道应该将他们的时间用在什么地方。他们所能控制的时间非常有限，他们会有系统地工作，来善用这有限的时间。（2）有效的管理者重视对外界的贡献。他们并非为工作而工作，而是为成果而工作。他们不会一接到工作就一头钻进去，更不会一开头就探究工作的技术和手段，他们会首先自问：“别人期望我做出什么成果？”（3）有效的管理者善于利用长处，包括自己的长处、上司的长处、同事的长处和下属的长处。他们还善于抓住有利形势，做他们能做的事。他们不会把工作建立在自己的短处上，也绝不会去做自己做不了的事。（4）有效的管理者集中精力于少数重要的领域，在这少数重要的领域中，如果能有优秀的绩效就可以产生卓越的成果。他们会按照工作的轻重缓急设定优先次序，而且坚守优先次序。他们别无选择，只能要事第一。重要的事先做，不重要的事放一放，甚至不做，两种事都做，反倒会一事无成。（5）最后，有效的管理者必须善于做有效的决策。他们知道有效的决策事关处事的条理和秩序问题，也就是如何按正确的次序采取正确的步骤。他们知道一项有效的决策，总是在“不同意见讨论”的基础上做出的判断，它绝不会是“一致意见”的产物。他们知道快速的决策多为错误的决策，真正不可或缺的决策数量并不多，但一定是根本性的决策。他们需要的是正确的战略，而不是令人眼花缭乱的战术。</p></blockquote><p>◆ 第2章 掌握自己的时间</p><blockquote><p>这三个步骤，是管理者有效性的基础：·记录时间；·管理时间；·统一安排时间。</p></blockquote><p>◆ 时间对管理者的压力</p><p>定期沟通非常重要~</p><blockquote><p>在大型组织中，如果知识工作者的绩效表现不错，往往是因为该组织的高级主管能定期抽出时间来与他们进行交流，甚至与一些资历较浅的知识工作者交流：“你认为我们组织的领导，对你的工作应该了解些什么？你对我们这个组织有什么看法？你觉得我们还有哪些尚未开拓的机会？你觉得我们有哪些尚未察觉的危机？还有，你希望从我这里知道些什么？”</p></blockquote><blockquote><p>管理理论中早就有所谓“管理幅度”之说。所谓管理幅度，是指一个管理者能有效地管理多少个工作上互有关联的人。</p></blockquote><blockquote><p>斯隆先生一向以知人善任而闻名。有人问他用人的秘诀是什么，据说他的回答是：“我没有秘诀。我只是有这样的感觉，我第一念就想到的人选，往往不会是最适当的人选。因此，我总要对整个思考和分析过程做好几次回顾之后，才做最后决定。”</p></blockquote><p>◆ 如何诊断自己的时间</p><blockquote><p>所以，要提高管理者的有效性，第一步就是记录其时间耗用的实际情形。</p></blockquote><blockquote><p>因此，第二个步骤就是要做有系统的时间管理。</p></blockquote><p>◆ 如何诊断自己的时间</p><blockquote><p>（1）首先要找出什么事根本不必做，这些事做了也完全是浪费时间，于最终的成果无助。将时间记录拿出来，逐项逐项地问：“这件事如果不做，会有什么后果？”如果认为“不会有任何影响”，那么这件事便该立刻取消。</p></blockquote><blockquote><p>（2）第二个该问的问题是：“时间记录上的哪些活动可以由别人代为参加而又不影响效果？”</p></blockquote><blockquote><p>（3）还有一项时间浪费的因素，是管理者自己可以控制并且可以消除的，这项因素是：管理者在浪费别人的时间。</p></blockquote><p>◆ 消除浪费时间的活动</p><blockquote><p>（1）首先要做的是，找出由于缺乏制度或远见而产生时间浪费的因素。应注意的现象，是机构中一而再、再而三出现同样的“危机”。同样的危机如果出现了第二次，就绝不应该再让它出现第三次。</p></blockquote><blockquote><p>（2）人员过多，也常造成时间的浪费。</p></blockquote><blockquote><p>（3）另一个常见的浪费时间的原因，是组织不健全。其表现就是会议太多。</p></blockquote><blockquote><p>我们之所以要开会，只是因为各有各的工作，要靠彼此合作才能完成某一特定任务。我们之所以要开会，只是因为某一情况所需的知识和经验，不能全部装在一个人的头脑里，需要集思广益。</p></blockquote><blockquote><p>（4）最后一项浪费时间的因素，是信息功能不健全。</p></blockquote><p>◆ 统一安排可以自由支配的时间</p><blockquote><p>一位管理者的职位越高，其不能自行支配的时间也一定越多。组织的规模越大，其用于维系组织运行，而非用于发挥组织功能及生产的时间也一定越多。</p></blockquote><blockquote><p>所以，时间管理的最后一步，应该是将可由管理者自行支配的零碎时间集中起来。</p></blockquote><p>◆ 第3章 我能贡献什么</p><blockquote><p>重视贡献是有效性的关键。所谓有效性，表现在以下三个方面：①自己的工作，包括工作内容、工作水准、工作标准及其影响；②自己与他人的关系，包括对上司、同事和下属；③各项管理手段的运用，例如会议或报告等。</p></blockquote><p>◆ 管理者的承诺</p><blockquote><p>重视贡献，才能使管理者的注意力不为其本身的专长所限，不为其本身的技术所限，不为其本身所属的部门所限，才能看到整体的绩效，同时也才能使他更加重视外部世界。</p></blockquote><blockquote><p>一般机构对成效的要求往往表现在以下三个方面：直接成果；树立新的价值观及对这些价值观的重新确认；培养与开发明天所需要的人才。</p></blockquote><blockquote><p>而一个组织，大体言之，正是克服这种限度的工具。组织如果不能持续存在，就是失败。所以，一个组织必须今天准备明天的接班人，其人力资源必须更新，必须经常提高水准。下一代的人，应能以这一代辛苦经营的成果为起点。因此，下一代的人是站在他们前辈的肩头，再开创新的高峰，并在此基础上为他们的下一代准备更高的基准线。</p></blockquote><p>◆ 正确的人际关系</p><blockquote><p>有效的人际关系，有下列4项基本要求，而着眼于贡献，正可满足这些条件：·互相沟通；·团队合作；·自我发展；·培养他人。</p></blockquote><p>◆ 第4章 如何发挥人的长处</p><blockquote><p>有效的管理者能使人发挥其长处。他知道只抓住缺点和短处是干不成任何事的，为实现目标，必须用人所长——用其同事之所长、用其上级之所长和用其本身之所长。利用好这些长处可以给你带来真正的机会。充分发挥人的长处，才是组织存在的唯一目的。要知道任何人都必定有很多缺点和短处，而缺点和短处几乎是不可能改变的，但是我们却可以设法使其不发生作用。管理者的任务，就是要充分运用每一个人的长处，共同完成任务。</p></blockquote><p>◆ 要用人所长</p><blockquote><p>管理者要运用人的长处，面临的第一关即在于择人。有效的管理者择人任事和升迁，都以一个人能做些什么为基础。所以，他的用人决策，不在于如何克服人的短处，而在于如何发挥人的长处。</p></blockquote><blockquote><p>美国的钢铁工业之父卡内基的墓志铭说得最为透彻：“这里躺着的人，知道选用比自己能力更强的人来为他工作。”</p></blockquote><blockquote><p>有效的管理者从来不问：“他能跟我合得来吗？”他们问的是：“他贡献了什么？”他们从来不问：“他不能做什么？”他们问的是：“他能把什么做好？”所以在用人时，他们用的都是在某一方面有所长的人，而不是在各方面都过得去的人。</p></blockquote><blockquote><p>当然，世上确有多才多艺的人，这就是通常所谓的“全才”。但真正能在多方面都有杰出造诣的人，至今还没有出现。达·芬奇算是多才多艺了，但他最突出的成就只是在绘画上。歌德的诗如果没有流传下来，那即使他对光学和哲学有研究，也不见得能在百科全书上找到他的赫赫大名。几位世人皆知的伟人尚且如此，更何况我们这些凡人。因此，一位管理者如果不能发掘人的长处，并设法使其长处发挥作用，那么他只有受到人之弱点、人之短处、人之缺失的影响，结果是既完不成任务，又缺乏有效性。用人时老是坚持客观上不可能达到的标准，或过多地强调别人的弱点，那纵然算不上是对人力资源的滥用，起码也是误用。</p></blockquote><blockquote><p>人际关系专家有一句俗语：“你要雇用一个人的手，就得雇用他整个的人。”同样的道理，一个人不可能只有长处，他必然也有短处。</p></blockquote><blockquote><p>我们常常可以听到这样的说法：能建立起第一流经营体制的管理者，通常不会与周围的同事及下属保持过分亲密的关系。不能根据个人的好恶来挑选人才，而应当看他们能干些什么，看他们的工作表现，绝不能看他们是否顺从自己。因此，为了确保能够选用适当的人选，管理者应该与直接的同事或下属保持适当的距离。</p></blockquote><blockquote><p>（1）卓有成效的管理者不会认为职位是上天或上帝创造的。职位是由人设计，是人都可能犯错。因此，他们绝不会设计一个“不可能达成”的职位，换言之，不会设计一个“常人”不可能胜任的职位。</p></blockquote><blockquote><p>（2）用人所长的第2个原则是：职位的要求要严格，而涵盖要广。这是说，合理的职位，是对具有才干的人的挑战。同时因为职位的涵盖很广，所以人们可以把与任务有关的优势转化为切实的成果。</p></blockquote><blockquote><p>（3）第3个原则，是卓有成效的管理者在用人时，会先考虑某人能做些什么，而不是先考虑职位的要求是什么。换言之，有效的管理者早在决定将某人安置于某职位之前，会先仔细考虑这个人的条件，而且他考虑时绝不会只局限于这个职位。</p></blockquote><blockquote><p>我们所能评估的，只有绩效。我们所应该评估的，也只有绩效。这是必须将职位设计得涵盖较广且具有挑战性的另一个原因。这也是个人必须认真考虑，自己能为组织做出什么贡献的原因，因为一个人的绩效如何，只有在组织希望此人做出具体成绩的背景下，才能评估出来。</p></blockquote><blockquote><p>但是，一套适当的考评方式，毕竟是不可少的。否则，当一个职务需要某人来承担时，就没办法对他做出正确的评价。因此，有效的管理者，通常总有他自己的一套与众不同的考评方式。这套方式，第一步是列出对某人过去职务和现任职务所期望的贡献，再把某人的实际绩效记录与这项期望贡献相对照，然后检讨下面的4个问题。①哪方面的工作他确实做得很好？②因此，哪方面的工作他可能会做得更好？③为了充分发挥他的长处，他还应该再学习或获得哪些知识？④如果我有个儿子或女儿，我愿意让我的子女在他的指导下工作吗？a.如果愿意，理由是什么？b.如果不愿意，理由是什么？</p></blockquote><blockquote><p>（4）第4个原则是，卓有成效的管理者知道在用人之所长的同时，必须容忍人之所短。</p></blockquote><blockquote><p>更重要的是，有效的管理者对一位得力的人才，绝不会说：“我少不了他，少了他，我的事就办不成了。”通常我们说“少不了某人”，其原因不外三点：一是某人其实并不行，不过是管理者没有对他苛求而已，他本人也只能在这种保护下生存；二是管理者本人的能力太差，实际上是误用了某人的才干来勉强支持一个自己很难站得住脚的上司；三是本来就潜伏着某项严重问题，因为误用某人的才干而将该项问题掩盖住了。</p></blockquote><blockquote><p>尽量发挥下属的长处，不但是管理者必须对机构承担的义务，更重要的是，这也是为人处世的道理：他应该协助下属得到应有的发展。</p></blockquote><blockquote><p>总结一句：用人所长是卓有成效的管理者必须具备的一种素质，是一个组织工作是否有效的关键，也是知识工作者和社会不可或缺的素质。</p></blockquote><p>◆ 如何管理上司</p><blockquote><p>在具体做法上当然应该谨慎小心。实际上，如果上级主管的能力不够，下属通常是无法爬升上去的。上司如果没有升迁，下属只好永远屈居其下。如果有一天上司因成绩不佳调职了，继任者也往往都是来自别的部门，很少在本单位中选人提升。而且新上司到任时，也总是带来他自己的亲信。反之，凡是成功而升迁得快的主管，其下属也是最容易成功的。</p></blockquote><blockquote><p>有效的管理者了解他的上司也是人（然而年轻的下属却不容易有此了解）。上司既然是人，所以肯定有其长处，也肯定有其短处。若能在上司的长处上下功夫，协助他做好能做的工作，便能使上司有效，下属也才能有效。反之，如果下属总强调上司的短处，那就像上司强调下属的短处一样，结果将一无所成。所以，有效的管理者常问：“我的上司究竟能做好什么？他曾有过什么成就？要使他发挥他的长处，他还需要知道些什么？他需要我完成什么？”至于上司不能做些什么，那就不必细究了。</p></blockquote><p>◆ 第5章 要事优先</p><blockquote><p>卓有成效的管理者总是把重要的事情放在前面先做（first things first），而且一次只做好一件事（do one thing at a time）。</p></blockquote><blockquote><p>有些人一事无成，而实际上他们却做得很吃力。第一，他们低估了完成一件任务所需的时间。他们总以为万事顺利，却总不免有出乎意料的情况发生。然而每个管理者都知道，没有任何事情会是一帆风顺。其实，所谓意料之外者，正应该在我们意料之中。而所谓意料之中，往往从来没有令人愉快的意外。所以，有效的管理者对时间需求的估计宁可有余，而不可不足。第二，一般的管理者（往往也是不大有效的管理者）总喜欢赶工——而赶工的结果，总不免使进度更加落后。有效的管理者不愿赛跑，他们按部就班，稳定前进。第三，一般的管理者喜欢同时着手几件要事，结果对每一件事，他们都无法获得足够的最少整块时间。只要任何一件事情受阻，全部事情也都会跟着受阻了。</p></blockquote><p>◆ 摆脱昨天</p><blockquote><p>杜邦公司（Du Pont）有一个好例子：某一产品或流程在“尚未”开始走下坡路之前，他们就毅然放弃。杜邦公司从来不将其有限的人力和资金，用来保卫昨天。但是大部分的公司，往往抱着另一种观点。他们总是说：“只要我们努力，我们总会有市场！”他们总是说：“我们公司靠这项产品起家，我们有责任让这项产品在市场上维持下去。”有趣的是，这样的公司，虽然常常选派他们的管理者参加各种有关创造力的研讨会，却偏偏找不出新的产品。而杜邦公司，却天天忙于生产和推出新的产品。</p></blockquote><p>◆ 先后次序的考虑</p><blockquote><p>以下是几条可帮助确定优先次序的重要原则，每条都与勇气密切相关：·重将来而不重过去；·重视机会，不能只看到困难；·选择自己的方向，而不盲从；·目标要高，要有新意，不能只求安全和容易。</p></blockquote><blockquote><p>所以真正的成就，只属于那些善于抓住机会选定研究课题的人，属于那些能把别人确立的准则只当作制约因素，而不当作决定因素的人。</p></blockquote><p>◆ 第6章 决策的要素</p><blockquote><p>有效的管理者不做太多的决策。他们所做的，都是重大的决策。他们重视的，是分辨什么问题为例行性的，什么问题为战略性的，而不重视“解决问题”。</p></blockquote><p>◆ 决策的五个要素</p><blockquote><p>决策的五个要素费尔和斯隆的决策，其主要的意义，绝不是表示决策应标新立异，也不是表示决策应有引人争议的特性，而是表示出决策的以下五点特征。（1）要确实了解问题的性质，如果问题是经常性的，那就只能通过一项建立规则或原则的决策才能解决。（2）要确实找出解决问题时必须满足的界限，换言之，应找出问题的“边界条件”。（3）仔细思考解决问题的正确方案是什么以及这些方案必须满足哪些条件，然后再考虑必要的妥协、适应及让步事项，以期该决策能被接受。（4）决策方案要同时兼顾执行措施，让决策变成可以被贯彻的行动。（5）在执行的过程中重视反馈，以印证决策的正确性及有效性。</p></blockquote><blockquote><p>按问题的发生情况来说，细究起来，不只有“经常”和“例外”两类，一般可以分成四类。第一类，是真正经常性的问题。发生的个别问题，只是一种表面现象。</p></blockquote><blockquote><p>第二类问题虽然是在某一特殊情况下偶然发生，但在实质上仍然是一项经常性问题。</p></blockquote><blockquote><p>第三类问题，才是真正偶发的特殊事件。</p></blockquote><blockquote><p>这也就是我们要介绍的第四类问题：首次出现的“经常事件”。</p></blockquote><blockquote><p>一位有效的决策者碰到问题，总是先假定该问题为“经常性质”。他总是先假定该问题是一种表面现象，另有根本性的问题存在。他要找出真正的问题，不会只满足于解决表面现象。</p></blockquote><blockquote><p>决策的第二个要素，在于确实了解决策应遵循的规范。决策的目标是什么？换言之，最低限度应该达成什么目的？应该满足什么条件？用科学的术语来说，这就是所谓“边界条件”。一项有效的决策必须符合边界条件，必须足以达成目的。</p></blockquote><blockquote><p>决策的第三个要素，是研究“正确”的决策是什么，而不是研究“能为人接受”的决策是什么。人总有采取折中办法的倾向，如果我们不知道符合规范及边界条件的“正确”决策是什么，就无法辨别正确的折中和错误的折中之间的区别，最终不免走到错误的折中的方向去。</p></blockquote><blockquote><p>决策的第四个要素，是化决策为行动。考虑边界条件，是决策过程中最难的一步；化决策为行动，则是最费时的一步。然而打从决策开始，我们就应该将行动的承诺纳入决策中，否则便是纸上谈兵。</p></blockquote><p>这总情况一般是国家发生战争或国内社会极其不稳定吧？在这种极端情况下，决策者还能保持冷静做出正确的决策，真的不容易~</p><blockquote><p>决策行动还必须与执行人员的工作能力相适应。<br>某一化学公司几年前曾发生大批资金冻结于非洲某两个国家，无法汇出之事。该公司为了保护这批资金，决定投资于非洲当地的企业。他们选定的企业，第一，对非洲当地的经济发展确有贡献；第二，不必从外面进口别的资源；第三，该企业将来成功后，一旦该国外汇解冻，应有希望转售于当地企业家，而将资金汇出。因此，该公司便积极着手筹备设厂，发展了一种简单的化学处理程序，加工当地出产的热带水果。那种水果，在那两个国家中都有丰富的产量，但过去因没有加工而腐烂率极高，不能远销西方市场。<br>经过一番努力，两个国家的工厂都经营得非常成功。但是其中一个厂的厂长过于卖力，设定了过高的技术和管理水平，结果在当地找不到适当人选来接管。而另一个厂的厂长却能充分考虑到当地人员的水平，故加工程序较为简单，管理也较为容易。结果全厂自下而上，都能聘到可用的当地人才。<br>几年过去，两个国家都可以将外汇汇出了。在这时，公司准备将两家工厂转售当地的企业家。然而，那家有声有色、水准极高的加工厂，由于当地没有适合的技术和管理人才始终无法售出，结果该厂只落得清算了事。而另一家水准平平的工厂，当地投资人都竞相购买，公司不但收回了原先投下的资金，而且还大获其利。<br>事实上两厂的加工程序和经验方式基本上是相同的，问题只是第一家工厂当初在决策时，没有考虑到：“这一决策应由谁来执行才能有效？他们能做些什么？”所以，终于失败了。</p></blockquote><blockquote><p>决策行动还必须与执行人员的工作能力相适应。某一化学公司几年前曾发生大批资金冻结于非洲某两个国家，无法汇出之事。该公司为了保护这批资金，决定投资于非洲当地的企业。他们选定的企业，第一，对非洲当地的经济发展确有贡献；第二，不必从外面进口别的资源；第三，该企业将来成功后，一旦该国外汇解冻，应有希望转售于当地企业家，而将资金汇出。因此，该公司便积极着手筹备设厂，发展了一种简单的化学处理程序，加工当地出产的热带水果。那种水果，在那两个国家中都有丰富的产量，但过去因没有加工而腐烂率极高，不能远销西方市场。经过一番努力，两个国家的工厂都经营得非常成功。但是其中一个厂的厂长过于卖力，设定了过高的技术和管理水平，结果在当地找不到适当人选来接管。而另一个厂的厂长却能充分考虑到当地人员的水平，故加工程序较为简单，管理也较为容易。结果全厂自下而上，都能聘到可用的当地人才。几年过去，两个国家都可以将外汇汇出了。在这时，公司准备将两家工厂转售当地的企业家。然而，那家有声有色、水准极高的加工厂，由于当地没有适合的技术和管理人才始终无法售出，结果该厂只落得清算了事。而另一家水准平平的工厂，当地投资人都竞相购买，公司不但收回了原先投下的资金，而且还大获其利。事实上两厂的加工程序和经验方式基本上是相同的，问题只是第一家工厂当初在决策时，没有考虑到：“这一决策应由谁来执行才能有效？他们能做些什么？”所以，终于失败了。</p></blockquote><blockquote><p>决策的最后一个要素，是应在决策中建立一项信息反馈制度，以便经常对决策所预期的成果做实际的印证。</p></blockquote><blockquote><p>自从电脑问世以来，这个问题更加重要了。因为有了电脑，决策者和执行者之间的关系可能更加疏远。所以，如果管理者老坐在办公室，不到工作现场，他和实际情形必将越来越脱节。电脑处理的只是抽象资料，抽象资料只有经过实践的检验之后才是可靠的。否则，电脑必将引人走入歧途。</p></blockquote><p>◆ 第7章 有效的决策</p><blockquote><p>有效的管理者都知道一项决策不是从搜集事实开始，而是先有自己的见解。这样做是正确的。因为凡在某一领域具有经验者，都应该有他的见解。假如说一个人在某一方面经验丰富，而竟然没有见解，那就说明此人没有敏锐的观察力，头脑迟钝。</p></blockquote><blockquote><p>说到判断，必须先有两项以上的方案，从其中选择一项。而且，如果说一项判断可以斩钉截铁地定其“对”与“错”，那也不称其为判断了。唯有在多项方案中，我们需凭借深入研究判断才能有所决定时，才称之为判断。</p></blockquote><blockquote><p>以企业投资为例，通常都有多种衡量方法。其一，衡量投入资金需要多久才能收回；其二，衡量投资的获利能力；其三，衡量投资收益的“现值”。</p></blockquote><blockquote><p>换句话说，管理者的决策不是从“众口一词”中得来的。好的决策，应以互相冲突的意见为基础，从不同的观点和不同的判断中选择。所以，除非有不同的见解，否则就不可能有决策。这是决策的第一条原则。</p></blockquote><p>◆ 反面意见的运用</p><blockquote><p>为什么该有反面意见，主要有三项理由。第一，唯有反面意见，才能保护决策者不致沦为组织的俘虏。在一个组织中，所有人都必有求于决策者，每个人都各有所求，都希望主管的决策能对自己有利。上至美国总统，下至企业机构中一位初级工程师修改某一工程设计莫不如此。唯一能突破这一陷阱，使决策者不致成为某方面的俘虏的办法，就在于引起争辩、掌握实据和经过深思熟虑的反面意见。</p></blockquote><blockquote><p>第二，反面意见本身，正是决策所需的“另一方案”。决策时只有一种方案，别无其他选择，无论多么深思熟虑，那与赌博何异？只有一种方案，失败的机会必高。</p></blockquote><blockquote><p>最后第三个理由，是反面意见可以激发想象力。</p></blockquote><blockquote><p>当然，有效的管理者知道世上有蠢才，也有恶作剧的人。但是，他绝不会将持不同意见者轻易地视为蠢才或捣蛋者，他总是假定任何人提出不同的意见，必是出于至诚。所以，某人的意见纵然错了，也是由于此人所看到的现实不同，或他所关切的是另一个不同的问题。因此，有效的管理者会问：“如果此人的立场果真正当、果真合理、果真有见地的话，此人的看法又将如何呢？”有效的管理者关切的是“理解”。只有在有了确切的理解之后，他才研究谁是谁非。</p></blockquote><blockquote><p>其实，2000年前罗马律法就曾说过：“行政长官不宜考虑鸡毛蒜皮之类的事情。”直到今天，我们的决策者还是需要好好学习这句话。</p></blockquote><blockquote><p>在这种情形下，有效的管理者会做比较：做了新决策，可能有什么收获和风险；不做又可能有什么损失。至于如何比较，通常没有一定的公式。但是，实际上只要遵循下面两项原则就够了：·如果利益远大于成本及风险，就该行动；·行动或不行动，切忌只做一半或折中。</p></blockquote><p>◆ 第8章 结论：管理者必须卓有成效</p><blockquote><p>（1）要做到卓有成效，首先要做的第一步，是记录好时间的使用情况。</p></blockquote><blockquote><p>（2）第二步，是管理者应把眼光集中在贡献上。</p></blockquote><blockquote><p>（3）第三步，充分发挥人的长处。</p></blockquote><blockquote><p>（4）本书第5章“要事优先”，可以与第2章“掌握自己的时间”互为呼应。</p></blockquote><blockquote><p>（5）本书最后几章研究有效的决策，其重心在于合理的行动。</p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;很早之前老师就推荐我们阅读管理大师德鲁克的书，但是因为自己对这方面的书籍兴趣不大，所以一直没有去找来看。直到最近空闲时间比较多，我才看完了彼得·德鲁克的《卓有成效的管理者》，受益匪浅。&lt;/p&gt;
&lt;p&gt;彼得·德鲁克曾任美国通用汽车公司、克莱斯勒公司、IBM公司等大企业的管理顾问，管理学是他一生主要的研究对象。此书是彼得·德鲁克40多年前写的一本著作，但是书中的思想和观点，现在读起来也仍然让人感到那么实际有效，感觉对自己的学习甚至是整个的人生规划都具有非常重要的指导意义。&lt;/p&gt;
&lt;p&gt;《卓有成效的管理者》这本书告诉我，一个优秀的管理者首先是自己的管理者。将自己有效管理起来，然后才能进一步去影响、指导他人。管理者在内心上和实际工作中的有效性训练很重要，要有一种倾向性的意识去自我提高，发展自己的有效性，这样才能成为一名真正的卓有成效的管理者。&lt;/p&gt;
&lt;p&gt;最后我想说，无论是否是管理者，都能从这本书里得到启发，因为管理自己也很重要。这本书的内容不多，但是干货非常多，我在里面划的笔记有87处之多。&lt;/p&gt;
    
    </summary>
    
    
      <category term="读书笔记" scheme="http://landerqi.com/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>使用curl命令模拟Post/Get请求</title>
    <link href="http://landerqi.com/2019/08/07/%E4%BD%BF%E7%94%A8curl%E5%91%BD%E4%BB%A4%E6%A8%A1%E6%8B%9FPost-Get%E8%AF%B7%E6%B1%82/"/>
    <id>http://landerqi.com/2019/08/07/使用curl命令模拟Post-Get请求/</id>
    <published>2019-08-07T03:06:08.000Z</published>
    <updated>2019-08-07T04:45:00.628Z</updated>
    
    <content type="html"><![CDATA[<p>有时需要测试接口，但是在服务器上又不方便使用postman, charles等工具，这时我们可以使用curl命令来模拟接口请求。</p><h4><span id="get-请求">get 请求</span></h4><figure class="highlight shell"><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">curl &quot;http://www.baidu.com&quot;        //  如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地</span><br><span class="line"></span><br><span class="line">curl -i &quot;http://www.baidu.com&quot;     // 显示全部信息</span><br><span class="line"></span><br><span class="line">curl -I &quot;http://www.baidu.com&quot;     // 只显示头部信息</span><br><span class="line"></span><br><span class="line">curl -v &quot;http://www.baidu.com&quot;     // 显示get请求全过程解析</span><br></pre></td></tr></table></figure><span id="more"></span><h4><span id="post-请求">post 请求</span></h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -d &quot;param1=value1&amp;param2=value2&quot; &quot;http://www.baidu.com&quot;</span><br></pre></td></tr></table></figure><p>自定义头信息传递给服务器:</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -H &quot;Content-Type:application/json&quot; -X POST -d &#x27;&#123;&quot;user&quot;: &quot;admin&quot;, &quot;passwd&quot;:&quot;12345678&quot;&#125;&#x27; http://127.0.0.1:8000/login  // json格式的post请求</span><br></pre></td></tr></table></figure><p>还可以传递多个头信息：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -H &quot;Content-Type:application/json&quot; -H &quot;accept-language:zh-cn&quot; -X POST -d &#x27;&#123;&quot;user&quot;: &quot;admin&quot;, &quot;passwd&quot;:&quot;12345678&quot;&#125;&#x27; http://127.0.0.1:8000/login  // json格式的post请求</span><br></pre></td></tr></table></figure><br>## More(curl --help):<h4><span id="1文件下载">1.文件下载</span></h4><p>curl命令可以用来执行下载、发送各种HTTP请求，指定HTTP头部等操作。如果系统没有curl可以使用<code>yum install curl</code>安装，也可以下载安装。curl是将下载文件输出到stdout，将进度信息输出到stderr，不显示进度信息使用<code>--silent</code>选项。</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl URL --silent   // 这条命令是将下载文件输出到终端，所有下载的数据都被写入到stdout</span><br></pre></td></tr></table></figure><p>使用选项<code>-O</code>将下载的数据写入到文件，必须使用文件的绝对地址：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl URL --silent -O</span><br></pre></td></tr></table></figure><p>选项<code>-o</code>将下载数据写入到指定名称的文件中，并使用–progress显示进度条：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl http://xxx.iso -o xxx.iso --progress</span><br><span class="line"><span class="meta">#</span><span class="bash"><span class="comment">######################################## 100.0%</span></span></span><br></pre></td></tr></table></figure><h4><span id="2用curl设置cookies">2.用curl设置cookies</span></h4><p>使用<code>--cookie &quot;COKKIES&quot;</code>选项来指定cookie，多个cookie使用分号分隔：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl http://yy..com --cookie &quot;user=root;pass=123456&quot;</span><br></pre></td></tr></table></figure><p>将cookie另存为一个文件，使用<code>--cookie-jar</code>选项：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl URL --cookie-jar cookie_file</span><br></pre></td></tr></table></figure><h4><span id="3用curl设置用户代理字符串">3.用curl设置用户代理字符串</span></h4><p>有些网站访问会提示只能使用IE浏览器来访问，这是因为这些网站设置了检查用户代理，可以使用curl把用户代理设置为IE，这样就可以访问了。使用<code>--user-agent</code>或者<code>-A</code>选项：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl URL --user-agent &quot;Mozilla/5.0&quot;</span><br><span class="line">curl URL -A &quot;Mozilla/5.0&quot;</span><br></pre></td></tr></table></figure><h4><span id="4用curl进行认证">4.用curl进行认证</span></h4><p>使用curl选项 -u 可以完成HTTP或者FTP的认证，可以指定密码，也可以不指定密码在后续操作中输入密码：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl -u user:pwd URL</span><br><span class="line">curl -u user URL</span><br></pre></td></tr></table></figure><h4><span id="5curl的带宽控制和下载配额">5.curl的带宽控制和下载配额</span></h4><p>使用<code>--limit-rate</code>限制curl的下载速度：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl URL --limit-rate 50k      // 命令中用k（千字节）和m（兆字节）指定下载速度限制。</span><br></pre></td></tr></table></figure><p>使用<code>--max-filesize</code>指定可下载的最大文件大小：</p><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl URL --max-filesize bytes  // 如果文件大小超出限制，命令则返回一个非0退出码，如果命令正常则返回0。</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;有时需要测试接口，但是在服务器上又不方便使用postman, charles等工具，这时我们可以使用curl命令来模拟接口请求。&lt;/p&gt;
&lt;h4 id=&quot;get-请求&quot;&gt;&lt;a href=&quot;#get-请求&quot; class=&quot;headerlink&quot; title=&quot;get 请求&quot;&gt;&lt;/a&gt;get 请求&lt;/h4&gt;&lt;figure class=&quot;highlight shell&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;curl &amp;quot;http://www.baidu.com&amp;quot;        //  如果这里的URL指向的是一个文件或者一幅图都可以直接下载到本地&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;curl -i &amp;quot;http://www.baidu.com&amp;quot;     // 显示全部信息&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;curl -I &amp;quot;http://www.baidu.com&amp;quot;     // 只显示头部信息&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;curl -v &amp;quot;http://www.baidu.com&amp;quot;     // 显示get请求全过程解析&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="Linux" scheme="http://landerqi.com/tags/Linux/"/>
    
  </entry>
  
  <entry>
    <title>SwitchHosts在win10上提示无权限问题</title>
    <link href="http://landerqi.com/2019/08/06/SwitchHosts%E5%9C%A8win10%E4%B8%8A%E6%8F%90%E7%A4%BA%E6%97%A0%E6%9D%83%E9%99%90%E9%97%AE%E9%A2%98/"/>
    <id>http://landerqi.com/2019/08/06/SwitchHosts在win10上提示无权限问题/</id>
    <published>2019-08-06T02:54:06.000Z</published>
    <updated>2019-08-12T11:43:38.440Z</updated>
    
    <content type="html"><![CDATA[<p>在win10系统中，有时右键选择以<strong>管理员身份</strong>启动switchhosts，依然会提示没有权限：</p><img src="https://fesystem.bs2dl.yy.com/1565060356811340" width="680" alt><p><strong>解决方法：</strong></p><span id="more"></span><ol><li>进入 C:\Windows\System32\drivers\etc，查看hosts文件属性:<img src="https://fesystem.bs2dl.yy.com/1565060666416975" width="580" alt></li><li>取消文件只读状态:<img src="https://fesystem.bs2dl.yy.com/1565060810732220" width="380" alt></li><li>修改用户权限:<img src="https://fesystem.bs2dl.yy.com/156506073178426" width="680" alt></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;在win10系统中，有时右键选择以&lt;strong&gt;管理员身份&lt;/strong&gt;启动switchhosts，依然会提示没有权限：&lt;/p&gt;
&lt;img src=&quot;https://fesystem.bs2dl.yy.com/1565060356811340&quot; width=&quot;680&quot; alt=&quot;&quot;&gt;

&lt;p&gt;&lt;strong&gt;解决方法：&lt;/strong&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="工具" scheme="http://landerqi.com/tags/%E5%B7%A5%E5%85%B7/"/>
    
      <category term="解决问题" scheme="http://landerqi.com/tags/%E8%A7%A3%E5%86%B3%E9%97%AE%E9%A2%98/"/>
    
  </entry>
  
  <entry>
    <title>卷积神经网络（CNN）原理及应用</title>
    <link href="http://landerqi.com/2019/07/04/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%EF%BC%88CNN%EF%BC%89%E5%8E%9F%E7%90%86%E5%8F%8A%E5%BA%94%E7%94%A8/"/>
    <id>http://landerqi.com/2019/07/04/卷积神经网络（CNN）原理及应用/</id>
    <published>2019-07-04T05:16:06.000Z</published>
    <updated>2019-07-04T07:11:01.478Z</updated>
    
    <content type="html"><![CDATA[<h2><span id="一-cnn原理">一、CNN原理</span></h2><p>卷积神经网络（CNN）主要是用于<strong>图像识别领域</strong>，它指的是一类网络，而不是某一种，其包含很多不同种结构的网络。不同的网络结构通常表现会不一样。从CNN的一些典型结构中，可以看到这些网络创造者非常有创造力，很多结构都非常巧妙，有机会再介绍现今主流的一些典型结构。 现在我们先来简单介绍一下卷积神经网络的原理。</p><p><strong>Very Deep Convolutional Networks for Large-Scale Image Recognition(2014), arXiv: 1409.1556:</strong></p><img src="https://rhinosystem.bs2dl.yy.com/fes1562146667035866" width="600" alt="VGG"><span id="more"></span><p>所有CNN最终都是把一张图片转化为<strong>特征向量</strong>，特征向量就相当于这张图片的DNA。就像<strong>上图VGG网络</strong>一样，通过多层的卷积，池化，全连接，降低图片维度，最后转化成了一个一维向量。这个向量就包含了图片的特征，当然这个特征不是肉眼上的图片特征，而是针对于神经网络的特征。</p><p><strong>之所以用VGG举例，因为他的网络结构非常简洁，清晰，相当好理解，简单介绍一下：</strong></p><ol><li>他的输入是一张224x224 的三通道图片，经过两层卷积之后，图片维度不变，通道数增加到了64。</li><li>之后那个红色的层是最大池化（max pooling）把图片维度变成了112x112。后续就是不断重复步骤1，2。</li><li>当变成1维向量之后，经过全连接（fully connected）加ReLU激活，softmax处理之后，变成了一个包含1000个数字的特征向量。</li></ol><p><strong>以上就是CNN所做的事情。</strong></p><h2><span id="二-cnn如何训练">二、 CNN如何训练</span></h2><h3><span id="1-卷积神经网络的前向传播过程">1. 卷积神经网络的前向传播过程</span></h3><p>在前向传播过程中，输入的图形数据经过多层卷积层的卷积和池化处理，提出特征向量，将特征向量传入全连接层中，得出分类识别的结果。当输出的结果与我们的期望值相符时，输出结果。</p><h4><span id="11-前向传播中的卷积操作">1.1 前向传播中的卷积操作</span></h4><ul><li>用一个小的权重矩阵去覆盖输入数据，对应位置加权相乘，其和作为结果的一个像素点；</li><li>这个权重在输入数据上滑动，形成一张新的矩阵：<br><img src="https://rhinosystem.bs2dl.yy.com/fes1562213771124475" width="200" alt="卷积"></li><li>这个权重矩阵称为卷积核（convolution kernel）；</li><li>其覆盖位置称为感受野（receptive field）；</li><li>参数共享；</li><li>滑动的像素数量叫做步长（stride）:<br><img src="https://rhinosystem.bs2dl.yy.com/fes1562214001010487" width="150" alt="卷积"></li><li>以卷积核的边还是中心点作为开始/结束的依据，决定了卷积的补齐（padding）方式。上面的图片是valid方式（这种方式新的矩阵维度可能会降低），而same方式则会在图像边缘用0补齐（这种方式图像维度不会降低）：<br><img src="https://rhinosystem.bs2dl.yy.com/fes1562214361852171" width="217" alt="卷积"></li><li>如果输入通道不只一个，那么卷积核是三阶的。所有通道的结果累加：<br><img src="https://rhinosystem.bs2dl.yy.com/fes1562214470197519" width="232" alt="卷积"></li></ul><p>如图：<br><br><img src="https://rhinosystem.bs2dl.yy.com/fes156221464750468" width="644" alt="卷积"></p><h4><span id="12-前向传播中的池化操作">1.2 前向传播中的池化操作</span></h4><p>池化又称为降采样（down_sampling），类型：</p><ol><li>最大池化（max pooling）：在感受野内取最大值输出；</li><li>平均池化（average pooling）：在感受野内取平均值进行输出；</li><li>其他如L2池化等。</li></ol><p>理解：</p><ul><li>一个选择框，将输入数据某个范围（矩阵）的所有数值进行相应计算，得到一个新的值，作为结果的一个像素点；</li><li>池化也有步长和补齐的概念，但是很少使用，通常选择框以不重叠的方式，在padding=0的输入数据上滑动，生成一张新的特征图：<br><img src="https://rhinosystem.bs2dl.yy.com/fes1562215203483923" width="290" alt="卷积"><img src="https://rhinosystem.bs2dl.yy.com/fes1562215198177517" width="574" alt="卷积"></li></ul><h4><span id="13-前向传播中的全连接">1.3 前向传播中的全连接</span></h4><p>特征图进过卷积层和下采样层的特征提取之后，将提取出来的特征传到全连接层中，通过全连接层，进行分类，获得分类模型，得到最后的结果。</p><h3><span id="2-卷积神经网络的反向传播过程">2. 卷积神经网络的反向传播过程</span></h3><p>当卷积神经网络输出的结果与我们的期望值不相符时，则进行反向传播过程。求出结果与期望值的误差，再将误差一层一层的返回，计算出每一层的误差，然后进行权值更新。</p><h3><span id="3-卷积神经网络的权值更新">3. 卷积神经网络的权值更新</span></h3><p>卷积层的误差更新过程为：将误差矩阵当做卷积核，卷积输入的特征图，并得到了权值的偏差矩阵，然后与原先的卷积核的权值相加，并得到了更新后的卷积核。</p><p><strong>卷积神经网络的训练过程流程图：</strong></p><img src="https://rhinosystem.bs2dl.yy.com/fes1562206854699605" width="500" alt="卷积神经网络的训练过程流程图"><p><strong>就像这张流程图一样，不断循环这个过程。最后得到一个稳定的权值和阈值。</strong></p><p>目前主流框架是**pytorch(facebook)和tensorflow(google)**。<br><br><strong>举个例子(一个手写数字识别网络，其代码量也就100多行)：</strong></p><figure class="highlight python"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> sys</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> tensorflow <span class="keyword">as</span> tf</span><br><span class="line"><span class="keyword">from</span> tensorflow.examples.tutorials.mnist <span class="keyword">import</span> input_data</span><br><span class="line"><span class="keyword">from</span> tinyenv.flags <span class="keyword">import</span> flags</span><br><span class="line"></span><br><span class="line">FLAGS = <span class="literal">None</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">train</span>():</span></span><br><span class="line">    mnist = input_data.read_data_sets(</span><br><span class="line">        FLAGS.data_dir, one_hot=<span class="literal">True</span>, fake_data=FLAGS.fake_data,</span><br><span class="line">    )</span><br><span class="line">    sess = tf.InteractiveSession()</span><br><span class="line"></span><br><span class="line">    <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;input&#x27;</span>):</span><br><span class="line">        x = tf.placeholder(tf.float32, [<span class="literal">None</span>, <span class="number">784</span>], name=<span class="string">&#x27;x-input&#x27;</span>)</span><br><span class="line">        y_ = tf.placeholder(tf.float32, [<span class="literal">None</span>, <span class="number">10</span>], name=<span class="string">&#x27;y-input&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;input_reshape&#x27;</span>):</span><br><span class="line">        image_shaped_input = tf.reshape(x, [-<span class="number">1</span>, <span class="number">28</span>, <span class="number">28</span>, <span class="number">1</span>])</span><br><span class="line">        tf.summary.image(<span class="string">&#x27;input&#x27;</span>, image_shaped_input, <span class="number">10</span>)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">weight_variable</span>(<span class="params">shape</span>):</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;Create a weight variable with appropriate initialization.&quot;&quot;&quot;</span></span><br><span class="line">        initial = tf.truncated_normal(shape, stddev=<span class="number">0.1</span>)</span><br><span class="line">        <span class="keyword">return</span> tf.Variable(initial)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">bias_variable</span>(<span class="params">shape</span>):</span></span><br><span class="line">        <span class="string">&quot;&quot;&quot;Create a bias variable with appropriate initialization.&quot;&quot;&quot;</span></span><br><span class="line">        initial = tf.constant(<span class="number">0.1</span>, shape=shape)</span><br><span class="line">        <span class="keyword">return</span> tf.Variable(initial)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">variable_summaries</span>(<span class="params">var</span>):</span></span><br><span class="line">        <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;summaries&#x27;</span>):</span><br><span class="line">            mean = tf.reduce_mean(var)</span><br><span class="line">            tf.summary.scalar(<span class="string">&#x27;mean&#x27;</span>, mean)</span><br><span class="line">            <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;stddev&#x27;</span>):</span><br><span class="line">                stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))</span><br><span class="line">            tf.summary.scalar(<span class="string">&#x27;stddev&#x27;</span>, stddev)</span><br><span class="line">            tf.summary.scalar(<span class="string">&#x27;max&#x27;</span>, tf.reduce_max(var))</span><br><span class="line">            tf.summary.scalar(<span class="string">&#x27;min&#x27;</span>, tf.reduce_min(var))</span><br><span class="line">            tf.summary.histogram(<span class="string">&#x27;histogram&#x27;</span>, var)</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">nn_layer</span>(<span class="params">input_tensor, input_dim, output_dim, layer_name,</span></span></span><br><span class="line"><span class="params"><span class="function">                 act=tf.nn.relu</span>):</span></span><br><span class="line">        <span class="keyword">with</span> tf.name_scope(layer_name):</span><br><span class="line">            <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;weights&#x27;</span>):</span><br><span class="line">                weights = weight_variable([input_dim, output_dim])</span><br><span class="line">                variable_summaries(weights)</span><br><span class="line">            <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;biases&#x27;</span>):</span><br><span class="line">                biases = bias_variable([output_dim])</span><br><span class="line">                variable_summaries(biases)</span><br><span class="line">            <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;Wx_plus_b&#x27;</span>):</span><br><span class="line">                preactivate = tf.matmul(input_tensor, weights) + biases</span><br><span class="line">                tf.summary.histogram(<span class="string">&#x27;pre_activations&#x27;</span>, preactivate)</span><br><span class="line">            activations = act(preactivate, name=<span class="string">&#x27;activation&#x27;</span>)</span><br><span class="line">            tf.summary.histogram(<span class="string">&#x27;activations&#x27;</span>, activations)</span><br><span class="line">            <span class="keyword">return</span> activations</span><br><span class="line"></span><br><span class="line">    hidden1 = nn_layer(x, <span class="number">784</span>, <span class="number">500</span>, <span class="string">&#x27;layer1&#x27;</span>)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;dropout&#x27;</span>):</span><br><span class="line">        keep_prob = tf.placeholder(tf.float32)</span><br><span class="line">        tf.summary.scalar(<span class="string">&#x27;dropout_keep_probability&#x27;</span>, keep_prob)</span><br><span class="line">        dropped = tf.nn.dropout(hidden1, keep_prob)</span><br><span class="line"></span><br><span class="line">    y = nn_layer(dropped, <span class="number">500</span>, <span class="number">10</span>, <span class="string">&#x27;layer2&#x27;</span>, act=tf.identity)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;cross_entropy&#x27;</span>):</span><br><span class="line">        diff = tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y)</span><br><span class="line">        <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;total&#x27;</span>):</span><br><span class="line">            cross_entropy = tf.reduce_mean(diff)</span><br><span class="line">    tf.summary.scalar(<span class="string">&#x27;cross_entropy&#x27;</span>, cross_entropy)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;train&#x27;</span>):</span><br><span class="line">        train_step = tf.train.AdamOptimizer(FLAGS.learning_rate).minimize(</span><br><span class="line">            cross_entropy)</span><br><span class="line"></span><br><span class="line">    <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;accuracy&#x27;</span>):</span><br><span class="line">        <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;correct_prediction&#x27;</span>):</span><br><span class="line">            correct_prediction = tf.equal(tf.argmax(y, <span class="number">1</span>), tf.argmax(y_, <span class="number">1</span>))</span><br><span class="line">        <span class="keyword">with</span> tf.name_scope(<span class="string">&#x27;accuracy&#x27;</span>):</span><br><span class="line">            accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))</span><br><span class="line">    tf.summary.scalar(<span class="string">&#x27;accuracy&#x27;</span>, accuracy)</span><br><span class="line"></span><br><span class="line">    merged = tf.summary.merge_all()</span><br><span class="line">    train_writer = tf.summary.FileWriter(FLAGS.log_dir + <span class="string">&#x27;/train&#x27;</span>, sess.graph)</span><br><span class="line">    test_writer = tf.summary.FileWriter(FLAGS.log_dir + <span class="string">&#x27;/test&#x27;</span>)</span><br><span class="line">    tf.global_variables_initializer().run()</span><br><span class="line"></span><br><span class="line">    <span class="function"><span class="keyword">def</span> <span class="title">feed_dict</span>(<span class="params">train</span>):</span></span><br><span class="line">        <span class="keyword">if</span> train <span class="keyword">or</span> FLAGS.fake_data:</span><br><span class="line">            xs, ys = mnist.train.next_batch(<span class="number">100</span>, fake_data=FLAGS.fake_data)</span><br><span class="line">            k = FLAGS.dropout</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            xs, ys = mnist.test.images, mnist.test.labels</span><br><span class="line">            k = <span class="number">1.0</span></span><br><span class="line">        <span class="keyword">return</span> &#123;x: xs, y_: ys, keep_prob: k&#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">for</span> i <span class="keyword">in</span> <span class="built_in">range</span>(FLAGS.iterations):</span><br><span class="line">        <span class="keyword">if</span> i % <span class="number">10</span> == <span class="number">0</span>:  <span class="comment"># Record summaries and test-set accuracy</span></span><br><span class="line">            summary, acc = sess.run(</span><br><span class="line">                [merged, accuracy], feed_dict=feed_dict(<span class="literal">False</span>))</span><br><span class="line">            test_writer.add_summary(summary, i)</span><br><span class="line">            <span class="built_in">print</span>(<span class="string">&#x27;Accuracy at step %s: %s&#x27;</span> % (i, acc))</span><br><span class="line">        <span class="keyword">else</span>:</span><br><span class="line">            <span class="keyword">if</span> i % <span class="number">100</span> == <span class="number">99</span>:</span><br><span class="line">                run_options = tf.RunOptions(</span><br><span class="line">                    trace_level=tf.RunOptions.FULL_TRACE)</span><br><span class="line">                run_metadata = tf.RunMetadata()</span><br><span class="line">                summary, _ = sess.run([merged, train_step],</span><br><span class="line">                                      feed_dict=feed_dict(<span class="literal">True</span>),</span><br><span class="line">                                      options=run_options,</span><br><span class="line">                                      run_metadata=run_metadata)</span><br><span class="line">                train_writer.add_run_metadata(run_metadata, <span class="string">&#x27;step%03d&#x27;</span> % i)</span><br><span class="line">                train_writer.add_summary(summary, i)</span><br><span class="line">            <span class="keyword">else</span>:</span><br><span class="line">                summary, _ = sess.run(</span><br><span class="line">                    [merged, train_step], feed_dict=feed_dict(<span class="literal">True</span>))</span><br><span class="line">                train_writer.add_summary(summary, i)</span><br><span class="line">    train_writer.close()</span><br><span class="line">    test_writer.close()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">main</span>(<span class="params">_</span>):</span></span><br><span class="line">    <span class="keyword">if</span> tf.gfile.Exists(FLAGS.log_dir):</span><br><span class="line">        tf.gfile.DeleteRecursively(FLAGS.log_dir)</span><br><span class="line">    tf.gfile.MakeDirs(FLAGS.log_dir)</span><br><span class="line">    train()</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span> __name__ == <span class="string">&#x27;__main__&#x27;</span>:</span><br><span class="line">    FLAGS = flags()</span><br><span class="line">    tf.app.run(main=main, argv=[sys.argv[<span class="number">0</span>]])</span><br><span class="line"></span><br></pre></td></tr></table></figure><p>训练之后，其识别准确度已达到96.7%:<br><br><img src="https://rhinosystem.bs2dl.yy.com/fes1562216103780594" width="700" alt="运行结果"></p><h2><span id="三-应用">三、 应用</span></h2><h3><span id="1-图片分类">1. 图片分类</span></h3><p>假设每张图片最后获得了6维特征向量v: [-0.24754368, -0.19974484, 0.45622883, 0.01130153, 0.08802839, -0.0419769]。<br><strong>我们要把图片分为3类， 那么分类矩阵就应该是6 x 3维的矩阵。</strong><br><strong>因为根据矩阵乘法：m,n维的矩阵乘以n,l维的矩阵，会得到一个m,l维的矩阵。</strong><br><strong>所以1 x 6维的矩阵乘以6 x 3维的矩阵最后会得到一个1 x 3的向量。</strong><br>如上述6维向量乘以分类矩阵之后得到：[-0.7777777, -0.9999999, 1.02222222]，那么很明显这张图片会被分到第三类。</p><h3><span id="2-相似图搜索">2. 相似图搜索</span></h3><p>广泛应用的人脸识别其实就是相似图搜索，比对两张照片是不是同一个人，当两张照片是同一个人时，他的<strong>欧氏距离</strong>会非常接近，反之。</p><img src="https://rhinosystem.bs2dl.yy.com/fes1562210643334534" width="616" alt="相似图搜索"><p>余弦距离：<br><br><img src="https://rhinosystem.bs2dl.yy.com/fes1562209420132736" width="346" alt="余弦距离"></p><h3><span id="3对抗样本">3.对抗样本</span></h3><p>对抗样本和神经网络训练过程不同的是，他是固定权重，更新输入数据。比如输入一张猫的图片，人为的修改一点图片数据，肉眼上看还是一只猫，但是你告诉神经网络这是狗。最后大量数据训练这后，神经网络会把这些图片错误的分类到狗这一类。</p><h2><span id="四-新技术">四、 新技术</span></h2><h3><span id="1-批归一化batch-normalization">1. 批归一化(Batch Normalization)</span></h3><p>相当于把数据缩放到了合适的位置，所以应该放在卷积之后，激活函数之前。能加快网络收敛速度。一堆公式，脑壳痛：</p><img src="https://rhinosystem.bs2dl.yy.com/fes1562210403365769" width="580" alt="批归一化"><h3><span id="2-dropout还没有合适的中文翻译">2. Dropout(还没有合适的中文翻译)</span></h3><p>应用广泛。在标准 Dropout 的每轮迭代中，网络中的每个神经元以 p 的概率被丢弃。Dropout能够有效的改善过拟合的情况，提升泛化能力。前几天google申请的Dropout专利生效了。<br>Dropout实现要点：</p><ul><li>一般是实施在分类器之前（论文是放在最后一层分类器之后）；</li><li>Dropout以概率p置零神经元，这种情况下，保留的神经元的输出要除以<code>1-p</code> (论文是在inference时把所有权重乘以p)；</li><li>通常p初始值0.5。</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h2 id=&quot;一、CNN原理&quot;&gt;&lt;a href=&quot;#一、CNN原理&quot; class=&quot;headerlink&quot; title=&quot;一、CNN原理&quot;&gt;&lt;/a&gt;一、CNN原理&lt;/h2&gt;&lt;p&gt;卷积神经网络（CNN）主要是用于&lt;strong&gt;图像识别领域&lt;/strong&gt;，它指的是一类网络，而不是某一种，其包含很多不同种结构的网络。不同的网络结构通常表现会不一样。从CNN的一些典型结构中，可以看到这些网络创造者非常有创造力，很多结构都非常巧妙，有机会再介绍现今主流的一些典型结构。 现在我们先来简单介绍一下卷积神经网络的原理。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Very Deep Convolutional Networks for Large-Scale Image Recognition(2014), arXiv: 1409.1556:&lt;/strong&gt;&lt;/p&gt;
&lt;img src=&quot;https://rhinosystem.bs2dl.yy.com/fes1562146667035866&quot; width=&quot;600&quot; alt=&quot;VGG&quot;&gt;
    
    </summary>
    
    
      <category term="AI" scheme="http://landerqi.com/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>卷积神经网络的发展</title>
    <link href="http://landerqi.com/2019/07/02/%E5%8D%B7%E7%A7%AF%E7%A5%9E%E7%BB%8F%E7%BD%91%E7%BB%9C%E7%9A%84%E5%8F%91%E5%B1%95/"/>
    <id>http://landerqi.com/2019/07/02/卷积神经网络的发展/</id>
    <published>2019-07-02T06:47:51.000Z</published>
    <updated>2019-10-28T03:24:58.511Z</updated>
    
    <content type="html"><![CDATA[<h4><span id="1968-hubel-amp-wiesel-猫脑实验">1968 Hubel &amp; Wiesel 猫脑实验</span></h4><p>Hubel和Wiesel干了一件事，他们将猫麻醉后，把电极插到其视觉神经上连接示波器，并给它们看不同的图像，观察脑电波的反应。他们发现猫看到鱼的图片神经元不会兴奋。但是却意外发现，切换幻灯片的时候猫的神经元会兴奋，也就是图片的边缘会引起猫咪神经元的兴奋。</p><p>由于这项发现，Hubel和Wiesel一起获得了1981年的诺贝尔奖。这项发现不仅在生物学上留下浓墨重彩的一笔，而且对20年后人工智能的发展埋下了伏笔。</p><h4><span id="1980-neocognitron">1980 Neocognitron</span></h4><p>日本科学家福岛邦彦提出了neocognitron，其目标是构建一个能够像人脑一样实现模式识别的网络结构从而帮助我们理解大脑的运作。并且他提出现在卷积在用的一系列前向传播的标准方法。<br>其网络结构：</p><p><img src="https://rhinosystem.bs2dl.yy.com/fes1562120587669746" alt="Neocognitron "></p><span id="more"></span><p>Neocoginitro主要贡献：</p><ol><li>将脑神经科学的结构在做了计算机模拟；</li><li>提出了现在CNN常用的step-by-step的filter；</li><li>使用ReLU来给网络提供非线性；</li><li>采用平均池化来做downsampling；</li><li>保证了网络的平移不变性；</li><li>实现了稀疏交互。</li></ol><p><strong>基本上大部分现代CNN的结构在这个模型上都已经得到了体现。</strong></p><h4><span id="1990-bp-for-cnn">1990 BP for CNN</span></h4><p>Yann Lecun将反向传播应用到了类似Neocoginitro的网络上来做有监督学习，实现一个手写数字识别的神经网络。<br>其网络结构：<br><img src="https://rhinosystem.bs2dl.yy.com/fes1562125399361159" alt="BP for CNN"></p><p>这里共有四层隐层和一层输出，其中H1和H3都是卷积层，而H2和H4都是downsampling( 降采样：降低数据采样率或分辨率的过程)层。这篇论文最重要的是它简化了卷积操作，便于将反向传播应用到CNN上，并且利用它解决了一个现实世界中的问题。</p><h4><span id="1998-lenet-5">1998 LeNet-5</span></h4><p>Gradient-Based Learning Applied to Document Recognition，依然是Yann Lecun提出的，手写数字识别从此进入工业，比如银行支票识别等等。网络结构：<br><img src="https://rhinosystem.bs2dl.yy.com/fes1562122326465889" alt="LeNet-5"></p><p>可以看出来，LeNet-5的结构和现在用的CNN网络结构已经非常接近了。这里网络层数加深到了7层，其中两层卷积两层池化。<br>LeNet-5标志着卷积神经网络的开端，因为当时计算机算力的限制，所以其使用了复杂的局部连接。并且当时并没有使用softmax和交叉熵，而是使用了欧式径向基函数和均方误差。</p><h4><span id="2006-jake-bouvrie">2006 Jake Bouvrie</span></h4><p>Notes on Convolutional Neural Networks(2006 Jake Bouvrie), 其明确了我们在优化神经网络时对权重更新的一些手段。</p><h4><span id="2012-alexnet">2012 AlexNet</span></h4><p>Imagenet classification with deep convolutional neural networks(Alex Net)。<br><strong>AlexNet的出现可以说是标志着神经网络的复苏和深度学习的崛起</strong>。</p><p>网络结构：<br><img src="https://rhinosystem.bs2dl.yy.com/fes1562123965895796" alt="AlexNet"></p><p>此网络特色：</p><ul><li>使用了ReLU作为激活函数；</li><li>使用了数据增强；</li><li>使用了mini-batch SGD；</li><li>在GPU上训练；</li><li>实现了Dropout层来避免过拟合。</li></ul><h4><span id="2015-resnet">2015 ResNet</span></h4><p>Deep residual network (ResNet)，第一个在ImageNet图片分类上表现超过人类水准的算法。<br>网络结构：<br><img src="https://s2.ax1x.com/2019/09/25/uZH9BD.gif" alt="ResNet"></p><p><img src="https://rhinosystem.bs2dl.yy.com/fes1562124809829776" alt="ResNet"><br>ResNet的特点：</p><ul><li>残差block；</li><li>堆叠式结构；</li><li>深度的突破与终结，其最多可以达到1000多层，不过随着层数的增加，网络的效果并不会变得越来越好。</li></ul><p>以上大致就是卷积神经网络发展比较重要的一些时点、事件。</p>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;1968-Hubel-amp-Wiesel-猫脑实验&quot;&gt;&lt;a href=&quot;#1968-Hubel-amp-Wiesel-猫脑实验&quot; class=&quot;headerlink&quot; title=&quot;1968 Hubel &amp;amp; Wiesel 猫脑实验&quot;&gt;&lt;/a&gt;1968 Hubel &amp;amp; Wiesel 猫脑实验&lt;/h4&gt;&lt;p&gt;Hubel和Wiesel干了一件事，他们将猫麻醉后，把电极插到其视觉神经上连接示波器，并给它们看不同的图像，观察脑电波的反应。他们发现猫看到鱼的图片神经元不会兴奋。但是却意外发现，切换幻灯片的时候猫的神经元会兴奋，也就是图片的边缘会引起猫咪神经元的兴奋。&lt;/p&gt;
&lt;p&gt;由于这项发现，Hubel和Wiesel一起获得了1981年的诺贝尔奖。这项发现不仅在生物学上留下浓墨重彩的一笔，而且对20年后人工智能的发展埋下了伏笔。&lt;/p&gt;
&lt;h4 id=&quot;1980-Neocognitron&quot;&gt;&lt;a href=&quot;#1980-Neocognitron&quot; class=&quot;headerlink&quot; title=&quot;1980 Neocognitron&quot;&gt;&lt;/a&gt;1980 Neocognitron&lt;/h4&gt;&lt;p&gt;日本科学家福岛邦彦提出了neocognitron，其目标是构建一个能够像人脑一样实现模式识别的网络结构从而帮助我们理解大脑的运作。并且他提出现在卷积在用的一系列前向传播的标准方法。&lt;br&gt;其网络结构：&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://rhinosystem.bs2dl.yy.com/fes1562120587669746&quot; alt=&quot;Neocognitron &quot;&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="AI" scheme="http://landerqi.com/tags/AI/"/>
    
  </entry>
  
  <entry>
    <title>一个简单的广播队列</title>
    <link href="http://landerqi.com/2018/10/25/%E4%B8%80%E4%B8%AA%E7%AE%80%E5%8D%95%E7%9A%84%E5%B9%BF%E6%92%AD%E9%98%9F%E5%88%97/"/>
    <id>http://landerqi.com/2018/10/25/一个简单的广播队列/</id>
    <published>2018-10-25T06:27:10.000Z</published>
    <updated>2019-07-02T06:28:51.121Z</updated>
    
    <content type="html"><![CDATA[<p><strong>记录一些需求开发中的小代码，如果以后有类似的功能需求，可快速复用。</strong></p><h3><span id="调用">调用：</span></h3><figure class="highlight javascript"><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"><span class="keyword">import</span> BroadcastQueue <span class="keyword">from</span> <span class="string">&#x27;./BroadcastQueue&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 初始化调用</span></span><br><span class="line"><span class="built_in">this</span>.broadcastQueue = <span class="keyword">new</span> BroadcastQueue(<span class="function">(<span class="params">data</span>) =&gt;</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.showHighlightTip(data);</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="title">showHighlightTip</span>(<span class="params">queueItem</span>)</span> &#123;</span><br><span class="line">    <span class="comment">// 取出队列 item后的处理逻辑</span></span><br><span class="line">    ...</span><br><span class="line">&#125;,</span><br><span class="line"></span><br><span class="line"><span class="comment">//  收到广播的时候，一条条push进队列</span></span><br><span class="line"><span class="built_in">this</span>.broadcastQueue.push(&#123;</span><br><span class="line">    tip,</span><br><span class="line">    <span class="attr">showBtn</span>: <span class="literal">false</span>,</span><br><span class="line">    <span class="attr">order</span>: <span class="number">3</span>,</span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 清除队列</span></span><br><span class="line"><span class="built_in">this</span>.broadcastQueue.clear()</span><br><span class="line"></span><br></pre></td></tr></table></figure><span id="more"></span><p><code>BroadcastQueue.js</code></p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 广播队列</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="class"><span class="keyword">class</span> <span class="title">BroadcastQueue</span> </span>&#123;</span><br><span class="line">  <span class="function"><span class="title">constructor</span>(<span class="params">onData</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.onData = onData;</span><br><span class="line">    <span class="built_in">this</span>.queue = [];</span><br><span class="line">    <span class="built_in">this</span>.isRun = <span class="literal">false</span>;</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">/**</span></span><br><span class="line"><span class="comment">   * 向队列中增加广播</span></span><br><span class="line"><span class="comment">   * <span class="doctag">@param <span class="type">&#123;Object&#125;</span> <span class="variable">data</span></span></span></span><br><span class="line"><span class="comment">   * <span class="doctag">@param <span class="type">&#123;Object&#125;</span> </span>tip 广播内容</span></span><br><span class="line"><span class="comment">   * <span class="doctag">@param <span class="type">&#123;boolean&#125;</span> </span>showBtn 是否展示围观按钮</span></span><br><span class="line"><span class="comment">   * <span class="doctag">@param <span class="type">&#123;number&#125;</span> </span>order 优先顺序，值较小的优先展示，如果值为-1表示立即展示</span></span><br><span class="line"><span class="comment">   */</span></span><br><span class="line">  <span class="function"><span class="title">push</span>(<span class="params">data</span>)</span> &#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;BroadcastQueue().push&#x27;</span>, <span class="built_in">JSON</span>.stringify(data));</span><br><span class="line">    <span class="keyword">if</span> (data.order == <span class="literal">null</span>) &#123; <span class="comment">// eslint-disable-line</span></span><br><span class="line">      <span class="comment">// 如果没有优先顺序，默认为低优先级，给一个较大的序号</span></span><br><span class="line">      data.order = <span class="number">100</span>; <span class="comment">// eslint-disable-line</span></span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">this</span>.queue.length === <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="built_in">this</span>.queue.push(data);</span><br><span class="line">    &#125; <span class="keyword">else</span> &#123;</span><br><span class="line">      <span class="keyword">for</span> (<span class="keyword">let</span> i = <span class="number">0</span>; i &lt; <span class="built_in">this</span>.queue.length; i += <span class="number">1</span>) &#123;</span><br><span class="line">        <span class="keyword">const</span> item = <span class="built_in">this</span>.queue[i];</span><br><span class="line">        <span class="keyword">if</span> (data.order &lt; item.order) &#123;</span><br><span class="line">          <span class="built_in">this</span>.queue.splice(i, <span class="number">0</span>, data);</span><br><span class="line">          <span class="keyword">break</span>;</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (i === <span class="built_in">this</span>.queue.length - <span class="number">1</span>) &#123;</span><br><span class="line">          <span class="built_in">this</span>.queue.push(data);</span><br><span class="line">          <span class="keyword">break</span>;</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">    <span class="built_in">this</span>.run();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="title">run</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">this</span>.isRun) &#123;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">this</span>.isRun = <span class="literal">true</span>;</span><br><span class="line">    <span class="built_in">this</span>.next();</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="function"><span class="title">next</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="keyword">if</span> (<span class="built_in">this</span>.queue.length === <span class="number">0</span>) &#123;</span><br><span class="line">      <span class="built_in">this</span>.isRun = <span class="literal">false</span>;</span><br><span class="line">      <span class="keyword">return</span>;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">const</span> data = <span class="built_in">this</span>.queue.shift();</span><br><span class="line">    <span class="built_in">this</span>.onData(data);</span><br><span class="line">    <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span><br><span class="line">      <span class="built_in">this</span>.next();</span><br><span class="line">    &#125;, <span class="number">10000</span>);</span><br><span class="line">  &#125;</span><br><span class="line"></span><br><span class="line">  <span class="comment">// 只清除order不为1的广播</span></span><br><span class="line">  <span class="function"><span class="title">clear</span>(<span class="params"></span>)</span> &#123;</span><br><span class="line">    <span class="built_in">this</span>.queue = <span class="built_in">this</span>.queue.filter(<span class="function"><span class="params">item</span> =&gt;</span> item.order === <span class="number">1</span>);</span><br><span class="line">    <span class="built_in">this</span>.isRun = <span class="literal">false</span>;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3><span id="其余部分代码">其余部分代码：</span></h3><p>因为广播展示区域高度是固定28px, 所以当内容高度大于容器高度时，需要一个滚动动画。<br><code>smartMarquee.vue</code></p><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line">&lt;template&gt;</span><br><span class="line">  <span class="xml"><span class="tag">&lt;<span class="name">div</span> <span class="attr">class</span>=<span class="string">&quot;smart-marquee&quot;</span> <span class="attr">:style</span>=<span class="string">&quot;&#123;height: `$&#123;height&#125;px`&#125;&quot;</span>&gt;</span></span></span><br><span class="line"><span class="xml">    <span class="tag">&lt;<span class="name">div</span> <span class="attr">ref</span>=<span class="string">&quot;content&quot;</span>&gt;</span></span></span><br><span class="line"><span class="xml">      <span class="tag">&lt;<span class="name">slot</span>&gt;</span><span class="tag">&lt;/<span class="name">slot</span>&gt;</span></span></span><br><span class="line"><span class="xml">    <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line"><span class="xml">  <span class="tag">&lt;/<span class="name">div</span>&gt;</span></span></span><br><span class="line">&lt;/template&gt;</span><br><span class="line"></span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">script</span>&gt;</span><span class="javascript"></span></span></span><br><span class="line"><span class="javascript"><span class="xml"><span class="keyword">export</span> <span class="keyword">default</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="attr">props</span>: [<span class="string">&#x27;height&#x27;</span>],</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="function"><span class="title">data</span>(<span class="params"></span>)</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">    <span class="keyword">return</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">      <span class="attr">diffH</span>: <span class="number">0</span>, <span class="comment">// 内容高于容器的高度</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">      <span class="attr">offset</span>: <span class="number">0</span>, <span class="comment">// 位移量，单位为px</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">    &#125;;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="function"><span class="title">mounted</span>(<span class="params"></span>)</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">    <span class="built_in">this</span>.initScroll();</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">  <span class="attr">methods</span>: &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">    <span class="function"><span class="title">initScroll</span>(<span class="params"></span>)</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">      <span class="built_in">this</span>.diffH = <span class="built_in">this</span>.$refs.content.clientHeight - <span class="built_in">this</span>.height;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">      <span class="built_in">console</span>.log(<span class="string">&#x27;diff&#x27;</span>, <span class="built_in">this</span>.diffH, <span class="string">&#x27;contentH&#x27;</span>, <span class="built_in">this</span>.$refs.content.clientHeight);</span></span></span><br><span class="line"><span class="javascript"><span class="xml">      <span class="keyword">if</span> (<span class="built_in">this</span>.diffH &lt;= <span class="number">10</span>) &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">        <span class="keyword">return</span>; <span class="comment">// 内容小于或略大于容器高度，不需要滚动</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">      &#125;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">      <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">        <span class="built_in">this</span>.scroll();</span></span></span><br><span class="line"><span class="javascript"><span class="xml">      &#125;, <span class="number">500</span>);</span></span></span><br><span class="line"><span class="javascript"><span class="xml">    &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span></span></span><br><span class="line"><span class="javascript"><span class="xml">    <span class="comment">// 滚动</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">    <span class="function"><span class="title">scroll</span>(<span class="params"></span>)</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">      <span class="built_in">window</span>.requestAnimationFrame(<span class="function">() =&gt;</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">        <span class="keyword">if</span> (<span class="built_in">this</span>.offset &lt; <span class="built_in">this</span>.diffH) &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">          <span class="built_in">this</span>.offset += <span class="number">0.2</span>;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">          <span class="built_in">this</span>.$refs.content.style.transform = <span class="string">`translateY(-<span class="subst">$&#123;<span class="built_in">this</span>.offset&#125;</span>px)`</span>;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">          <span class="built_in">this</span>.scroll(); <span class="comment">// 递归调用，继续滚动</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">        &#125; <span class="keyword">else</span> &#123; <span class="comment">// 已经完成滚动，重新开始</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">          <span class="comment">// 过一段时间后再重新开始</span></span></span></span><br><span class="line"><span class="javascript"><span class="xml">          <span class="built_in">setTimeout</span>(<span class="function">() =&gt;</span> &#123;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">            <span class="built_in">this</span>.offset = <span class="number">0</span>;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">            <span class="built_in">this</span>.$refs.content.style.transform = <span class="string">&#x27;translateY(0)&#x27;</span>;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">            <span class="built_in">this</span>.scroll();</span></span></span><br><span class="line"><span class="javascript"><span class="xml">          &#125;, <span class="number">500</span>);</span></span></span><br><span class="line"><span class="javascript"><span class="xml">        &#125;</span></span></span><br><span class="line"><span class="javascript"><span class="xml">      &#125;);</span></span></span><br><span class="line"><span class="javascript"><span class="xml">    &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">  &#125;,</span></span></span><br><span class="line"><span class="javascript"><span class="xml">&#125;;</span></span></span><br><span class="line"><span class="javascript"><span class="xml"></span><span class="tag">&lt;/<span class="name">script</span>&gt;</span></span></span><br><span class="line"></span><br><span class="line"><span class="xml"><span class="tag">&lt;<span class="name">style</span> <span class="attr">lang</span>=<span class="string">&quot;scss&quot;</span> <span class="attr">scoped</span>&gt;</span><span class="css"></span></span></span><br><span class="line"><span class="css"><span class="xml"><span class="selector-class">.smart-marquee</span> &#123;</span></span></span><br><span class="line"><span class="css"><span class="xml">  <span class="attribute">position</span>: relative;</span></span></span><br><span class="line"><span class="css"><span class="xml">  <span class="attribute">overflow</span>: hidden;</span></span></span><br><span class="line"><span class="css"><span class="xml">  <span class="selector-class">.name</span> &#123;</span></span></span><br><span class="line"><span class="css"><span class="xml">    <span class="attribute">max-width</span>: <span class="number">71px</span>;</span></span></span><br><span class="line"><span class="css"><span class="xml">    <span class="attribute">display</span>: inline-block;</span></span></span><br><span class="line"><span class="css"><span class="xml">    <span class="attribute">white-space</span>: nowrap;</span></span></span><br><span class="line"><span class="css"><span class="xml">    <span class="attribute">text-overflow</span>: ellipsis;</span></span></span><br><span class="line"><span class="css"><span class="xml">    <span class="attribute">overflow</span>: hidden;</span></span></span><br><span class="line"><span class="css"><span class="xml">    <span class="attribute">vertical-align</span>: middle;</span></span></span><br><span class="line"><span class="css"><span class="xml">    <span class="attribute">margin-top</span>: -<span class="number">3px</span>;</span></span></span><br><span class="line"><span class="css"><span class="xml">  &#125;</span></span></span><br><span class="line"><span class="css"><span class="xml">&#125;</span></span></span><br><span class="line"><span class="css"><span class="xml"></span><span class="tag">&lt;/<span class="name">style</span>&gt;</span></span></span><br><span class="line"></span><br></pre></td></tr></table></figure><figure class="highlight javascript"><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></pre></td><td class="code"><pre><span class="line">&lt;smart-marquee :height=<span class="string">&quot;28&quot;</span>&gt;</span><br><span class="line">    <span class="xml"><span class="tag">&lt;<span class="name">span</span> <span class="attr">v-for</span>=<span class="string">&quot;(item, index) in data.tips.content.text&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="xml">        <span class="attr">:key</span>=<span class="string">&quot;index&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="xml">        <span class="attr">:style</span>=<span class="string">&quot;&#123;color: item.color, fontSize: item.size + &#x27;px&#x27;&#125;&quot;</span></span></span></span><br><span class="line"><span class="tag"><span class="xml">    &gt;</span>&#123;&#123;utils.base64_utf8_decode(item.text)&#125;&#125;<span class="tag">&lt;/<span class="name">span</span>&gt;</span></span></span><br><span class="line">&lt;/smart-marquee&gt;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;strong&gt;记录一些需求开发中的小代码，如果以后有类似的功能需求，可快速复用。&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;调用：&quot;&gt;&lt;a href=&quot;#调用：&quot; class=&quot;headerlink&quot; title=&quot;调用：&quot;&gt;&lt;/a&gt;调用：&lt;/h3&gt;&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;14&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;15&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;16&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;17&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;18&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;19&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;20&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;21&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;22&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;23&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;import&lt;/span&gt; BroadcastQueue &lt;span class=&quot;keyword&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&amp;#x27;./BroadcastQueue&amp;#x27;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// 初始化调用&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;this&lt;/span&gt;.broadcastQueue = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; BroadcastQueue(&lt;span class=&quot;function&quot;&gt;(&lt;span class=&quot;params&quot;&gt;data&lt;/span&gt;) =&amp;gt;&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;this&lt;/span&gt;.showHighlightTip(data);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;title&quot;&gt;showHighlightTip&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;queueItem&lt;/span&gt;)&lt;/span&gt; &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;comment&quot;&gt;// 取出队列 item后的处理逻辑&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    ...&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;//  收到广播的时候，一条条push进队列&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;this&lt;/span&gt;.broadcastQueue.push(&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    tip,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;attr&quot;&gt;showBtn&lt;/span&gt;: &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;attr&quot;&gt;order&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;,&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// 清除队列&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;this&lt;/span&gt;.broadcastQueue.clear()&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="javascript" scheme="http://landerqi.com/tags/javascript/"/>
    
      <category term="codebase" scheme="http://landerqi.com/tags/codebase/"/>
    
  </entry>
  
  <entry>
    <title>javascript-patterns学习笔记（三）</title>
    <link href="http://landerqi.com/2018/09/04/javascript-patterns%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%88%E4%B8%89%EF%BC%89/"/>
    <id>http://landerqi.com/2018/09/04/javascript-patterns学习笔记（三）/</id>
    <published>2018-09-04T12:18:02.000Z</published>
    <updated>2019-07-02T06:28:51.116Z</updated>
    
    <content type="html"><![CDATA[<p><strong>callback</strong><br>一个回调的例子</p><p>我们从一个例子开始，首先介绍无回调的情况，然后在作修改。假设你有一个通用的函数，用来完成某种复杂的逻辑并返回一大段数据。假设我们用findNodes()来命名这个通用函数，这个函数用来对DOM树进行遍历，并返回我所感兴趣的页面节点：</p><figure class="highlight actionscript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> findNodes = <span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> i = <span class="number">100000</span>, <span class="comment">// big, heavy loop</span></span><br><span class="line">        nodes = [], <span class="comment">// stores the result</span></span><br><span class="line">        found; <span class="comment">// the next node found</span></span><br><span class="line">    <span class="keyword">while</span> (i) &#123;</span><br><span class="line">        i -= <span class="number">1</span>;</span><br><span class="line">        <span class="comment">// complex logic here...</span></span><br><span class="line">        nodes.push(found);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> nodes;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><span id="more"></span><p>保持这个函数的功能的通用性并一贯返回DOM节点组成的数组，并不会发生对节点的实际操作，这是一个不错的注意。可以将操作节点的逻辑放入另外一个函数中，比如放入一个hide()函数中，这个函数用来隐藏页面中的节点元素：</p><figure class="highlight maxima"><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"><span class="built_in">var</span> hide = function (nodes) &#123;</span><br><span class="line">    <span class="built_in">var</span> i = <span class="number">0</span>, <span class="built_in">max</span> = nodes.<span class="built_in">length</span>;</span><br><span class="line">    <span class="keyword">for</span> (; i &lt; <span class="built_in">max</span>; i += <span class="number">1</span>) &#123;</span><br><span class="line">        nodes[i].<span class="built_in">style</span>.<span class="built_in">display</span> = <span class="string">&quot;none&quot;</span>;</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">// executing the <span class="built_in">functions</span></span><br><span class="line">hide(findNodes());</span><br></pre></td></tr></table></figure><p>这个实现的效率并不高，因为它将findNodes()所返回的节点数组重新遍历了一遍。最好在findNodes()中选择元素的时候就直接应用hide()操作，这样就能避免第二次的遍历，从而提高效率。但如果将hide()的逻辑写死在findNodes()的函数体内，findNodes()就变得不再通用了（译注：如果我将hide()的逻辑替换成其他逻辑怎么办呢？），因为修改逻辑和遍历逻辑耦合在一起了。如果使用回调模式，则可以将隐藏节点的逻辑写入回调函数，将其传入findNodes()中适时执行：</p><figure class="highlight actionscript"><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"><span class="comment">// refactored findNodes() to accept a callback</span></span><br><span class="line"><span class="keyword">var</span> findNodes = <span class="function"><span class="keyword">function</span> <span class="params">(callback)</span> </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> i = <span class="number">100000</span>,</span><br><span class="line">        nodes = [],</span><br><span class="line">        found;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// check if callback is callable</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback !== <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">        callback = <span class="literal">false</span>;</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">while</span> (i) &#123;</span><br><span class="line">        i -= <span class="number">1</span>;</span><br><span class="line"></span><br><span class="line">        <span class="comment">// complex logic here...</span></span><br><span class="line"></span><br><span class="line">        <span class="comment">// now callback:</span></span><br><span class="line">        <span class="keyword">if</span> (callback) &#123;</span><br><span class="line">            callback(found);</span><br><span class="line">        &#125;</span><br><span class="line"></span><br><span class="line">        nodes.push(found);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> nodes;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>这里的实现比较直接，findNodes()多作了一个额外工作，就是检查回调函数是否存在，如果存在的话就执行它。回调函数是可选的，因此修改后的findNodes()也是和之前一样使用，是可以兼容旧代码和旧API的。</p><p>这时hide()的实现就非常简单了，因为它不用对元素列表做任何遍历了：</p><figure class="highlight actionscript"><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"><span class="comment">// a callback function</span></span><br><span class="line"><span class="keyword">var</span> hide = <span class="function"><span class="keyword">function</span> <span class="params">(node)</span> </span>&#123;</span><br><span class="line">    node.style.display = <span class="string">&quot;none&quot;</span>;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// find the nodes and hide them as you go</span></span><br><span class="line">findNodes(hide);</span><br></pre></td></tr></table></figure><p>正如代码中所示，回调函数可以是事先定义好的，也可以是一个匿名函数，你也可以将其称作main函数，比如这段代码，我们利用同样的通用函数findNodes()来完成显示元素的操作：</p><figure class="highlight reasonml"><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 class="comment">// passing an anonymous callback</span></span><br><span class="line">find<span class="constructor">Nodes(<span class="params">function</span> (<span class="params">node</span>)</span> &#123;</span><br><span class="line">    node.style.display = <span class="string">&quot;block&quot;</span>;</span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p><strong>回调和作用域</strong></p><p>在上一个例子中，执行回调函数的写法是：</p><figure class="highlight abnf"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">callback(parameters)<span class="comment">;</span></span><br></pre></td></tr></table></figure><p>尽管这种写法可以适用大多数的情况，而且足够简单，但还有一些场景，回调函数不是匿名函数或者全局函数，而是对象的方法。如果回调函数中使用this指向它所属的对象，则回调逻辑往往并不像我们希望的那样执行。</p><p>假设回调函数是paint()，它是myapp的一个方法：</p><figure class="highlight actionscript"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> myapp = &#123;&#125;;</span><br><span class="line">myapp.color = <span class="string">&quot;green&quot;</span>;</span><br><span class="line">myapp.paint = <span class="function"><span class="keyword">function</span> <span class="params">(node)</span> </span>&#123;</span><br><span class="line">    node.style.color = <span class="keyword">this</span>.color;</span><br><span class="line">&#125;;</span><br><span class="line">函数findNodes()大致如下：</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> findNodes = <span class="function"><span class="keyword">function</span> <span class="params">(callback)</span> </span>&#123;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">        callback(found);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p><strong>当你调用findNodes(myapp.paint)，运行结果和我们期望的不一致，因为this.color未定义。因为findNodes()是全局函数，this指向的是全局对象。如果findNodes()是dom对象的方法（类似dom.findNodes()），那么回调函数内的this则指向dom，而不是myapp。</strong></p><p><strong>解决办法是，除了传入回调函数，还需将回调函数所属的对象当作参数传进去：</strong></p><figure class="highlight reasonml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">find<span class="constructor">Nodes(<span class="params">myapp</span>.<span class="params">paint</span>, <span class="params">myapp</span>)</span>;</span><br></pre></td></tr></table></figure><p>同样需要修改findNodes()的逻辑，增加对传入的对象的绑定：</p><figure class="highlight actionscript"><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"><span class="keyword">var</span> findNodes = <span class="function"><span class="keyword">function</span> <span class="params">(callback, callback_obj)</span> </span>&#123;</span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">        callback.call(callback_obj, found);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>在后续的章节会对call()和apply()有更详细的讲述。</p><p>其实还有一种替代写法，就是将函数当作字符串传入findNodes()，这样就不必再写一次对象了，换句话说：</p><figure class="highlight reasonml"><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">find<span class="constructor">Nodes(<span class="params">myapp</span>.<span class="params">paint</span>, <span class="params">myapp</span>)</span>;</span><br><span class="line"><span class="comment">// 可以写成：</span></span><br><span class="line">find<span class="constructor">Nodes(<span class="string">&quot;paint&quot;</span>, <span class="params">myapp</span>)</span>;</span><br></pre></td></tr></table></figure><p>在findNodes()中的逻辑则需要修改为：</p><figure class="highlight actionscript"><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"><span class="keyword">var</span> findNodes = <span class="function"><span class="keyword">function</span> <span class="params">(callback, callback_obj)</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback === <span class="string">&quot;string&quot;</span>) &#123;</span><br><span class="line">        callback = callback_obj[callback];</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    <span class="comment">//...</span></span><br><span class="line">    <span class="keyword">if</span> (<span class="keyword">typeof</span> callback === <span class="string">&quot;function&quot;</span>) &#123;</span><br><span class="line">        callback.call(callback_obj, found);</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="comment">// ...</span></span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><hr><p><strong>立即执行的函数好处和用法</strong></p><p>立即执行的函数应用很广泛。它可以帮助我们做一些不想留下全局变量的工作。所有定义的变量都只是立即执行的函数的本地变量，你完全不用担心临时变量会污染全局对象。</p><p><strong>立即执行的函数还有一些名字，比如“自调用函数”或者“自执行函数”，因为这些函数会在被定义后立即执行自己。</strong><br>这种模式也经常被用到书签代码中，因为书签代码会在任何一个页面运行，所以需要非常苛刻地保持全局命名空间干净。</p><p>这种模式也可以让你包裹一些独立的特性到一个封闭的模块中。设想你的页面是静态的，在没有JavaScript的时候工作正常，然后，本着渐进增强的精神，你给页面加入了一点增加代码。这时候，你就可以把你的代码（也可以叫“模块”或者“特性”）放到一个立即执行的函数中并且保证页面在有没有它的时候都可以正常工作。然后你就可以加入更多的增强特性，或者对它们进行移除、进行独立测试或者允许用户禁用等等。</p><p>你可以使用下面的模板定义一段函数代码，我们叫它module1：</p><figure class="highlight actionscript"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// module1 defined in module1.js</span></span><br><span class="line">(<span class="function"><span class="keyword">function</span> <span class="params">()</span> </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="comment">// all the module 1 code ...</span></span><br><span class="line"></span><br><span class="line">&#125;());</span><br></pre></td></tr></table></figure><p>立即初始化的对象</p><p>还有另外一种可以避免污染全局作用域的方法，和前面描述的立即执行的函数相似，叫做“立即初始化的对象”模式。这种模式使用一个带有init()方法的对象来实现，这个方法在对象被创建后立即执行。初始化的工作由init()函数来完成。</p><p>下面是一个立即初始化的对象模式的例子：</p><figure class="highlight kotlin"><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></pre></td><td class="code"><pre><span class="line">(&#123;</span><br><span class="line">    <span class="comment">// here you can define setting values</span></span><br><span class="line">    <span class="comment">// a.k.a. configuration constants</span></span><br><span class="line">    maxwidth: <span class="number">600</span>,</span><br><span class="line">    maxheight: <span class="number">400</span>,</span><br><span class="line"></span><br><span class="line">    <span class="comment">// you can also define utility methods</span></span><br><span class="line">    gimmeMax: function () &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">this</span>.maxwidth + <span class="string">&quot;x&quot;</span> + <span class="keyword">this</span>.maxheight;</span><br><span class="line">    &#125;,</span><br><span class="line"></span><br><span class="line">    <span class="comment">// initialize</span></span><br><span class="line">    <span class="keyword">init</span>: function () &#123;</span><br><span class="line">        console.log(<span class="keyword">this</span>.gimmeMax());</span><br><span class="line">        <span class="comment">// more init tasks...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;).<span class="keyword">init</span>();</span><br></pre></td></tr></table></figure><p>你也可以将对象字面量和init()调用一起写到括号里面。简单地说，下面两种语法都是有效的：</p><figure class="highlight nim"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">(<span class="meta">&#123;...&#125;</span>).init();</span><br><span class="line">(<span class="meta">&#123;...&#125;</span>.init());</span><br></pre></td></tr></table></figure><p><strong>这种模式的一个弊端是，JavaScript压缩工具可能不能像压缩一段包裹在函数中的代码一样有效地压缩这种模式的代码。这些私有的属性和方法不被会重命名为一些更短的名字，因为从压缩工具的角度来看，保证压缩的可靠性更重要。在写作本书的时候，Google出品的Closure Compiler的“advanced”模式是唯一会重命名立即初始化的对象的属性的压缩工具。一个压缩后的样例是这样：</strong></p><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">(&#123;<span class="attr">d</span>:<span class="number">600</span>,<span class="attr">c</span>:<span class="number">400</span>,<span class="attr">a</span>:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;<span class="keyword">return</span> <span class="built_in">this</span>.d+<span class="string">&quot;x&quot;</span>+<span class="built_in">this</span>.c&#125;,<span class="attr">b</span>:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>&#123;<span class="built_in">console</span>.log(<span class="built_in">this</span>.a())&#125;&#125;).b();</span><br></pre></td></tr></table></figure><p><strong>这种模式主要用于一些一次性的工作，并且在init()方法执行完后就无法再次访问到这个对象。如果希望在这些工作完成后保持对对象的引用，只需要简单地在init()的末尾加上return this;即可。</strong></p><hr><p><strong>条件初始化</strong></p><p>条件初始化（也叫条件加载）是一种优化模式。当你知道某种条件在整个程序生命周期中都不会变化的时候，那么对这个条件的探测只做一次就很有意义。浏览器探测（或者特征检测）是一个典型的例子。</p><p>举例说明，当你探测到XMLHttpRequest被作为一个本地对象支持时，就知道浏览器不会在程序执行过程中改变这一情况，也不会出现突然需要去处理ActiveX对象的情况。当环境不发生变化的时候，你的代码就没有必要在需要在每次XHR对象时探测一遍（并且得到同样的结果）。</p><p>另外一些可以从条件初始化中获益的场景是获得一个DOM元素的computed styles或者是绑定事件处理函数。大部分程序员在他们的客户端编程生涯中都编写过事件绑定和取消绑定相关的组件，像下面的例子：</p><figure class="highlight typescript"><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"><span class="comment">// BEFORE</span></span><br><span class="line"><span class="keyword">var</span> utils = &#123;</span><br><span class="line">    <span class="attr">addListener</span>: <span class="function"><span class="keyword">function</span> (<span class="params">el, <span class="keyword">type</span>, fn</span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">window</span>.addEventListener === <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">            el.addEventListener(<span class="keyword">type</span>, fn, <span class="literal">false</span>);</span><br><span class="line">        &#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">document</span>.attachEvent === <span class="string">&#x27;function&#x27;</span>) &#123; <span class="comment">// IE</span></span><br><span class="line">            el.attachEvent(<span class="string">&#x27;on&#x27;</span> + <span class="keyword">type</span>, fn);</span><br><span class="line">        &#125; <span class="keyword">else</span> &#123; <span class="comment">// older browsers</span></span><br><span class="line">            el[<span class="string">&#x27;on&#x27;</span> + <span class="keyword">type</span>] = fn;</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">removeListener</span>: <span class="function"><span class="keyword">function</span> (<span class="params">el, <span class="keyword">type</span>, fn</span>) </span>&#123;</span><br><span class="line">        <span class="comment">// pretty much the same...</span></span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p>这段代码的问题就是效率不高。每当你执行utils.addListener()或者utils.removeListener()时，同样的检查都会被重复执行。</p><p>如果使用条件初始化，那么浏览器探测的工作只需要在初始化代码的时候执行一次。在初始化的时候，代码探测一次环境，然后重新定义这个函数在剩下来的程序生命周期中应该怎样工作。下面是一个例子，看看如何达到这个目的：</p><figure class="highlight typescript"><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"><span class="comment">// AFTER</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// the interface</span></span><br><span class="line"><span class="keyword">var</span> utils = &#123;</span><br><span class="line">    <span class="attr">addListener</span>: <span class="literal">null</span>,</span><br><span class="line">    <span class="attr">removeListener</span>: <span class="literal">null</span></span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// the implementation</span></span><br><span class="line"><span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">window</span>.addEventListener === <span class="string">&#x27;function&#x27;</span>) &#123;</span><br><span class="line">    utils.addListener = <span class="function"><span class="keyword">function</span> (<span class="params">el, <span class="keyword">type</span>, fn</span>) </span>&#123;</span><br><span class="line">        el.addEventListener(<span class="keyword">type</span>, fn, <span class="literal">false</span>);</span><br><span class="line">    &#125;;</span><br><span class="line">    utils.removeListener = <span class="function"><span class="keyword">function</span> (<span class="params">el, <span class="keyword">type</span>, fn</span>) </span>&#123;</span><br><span class="line">        el.removeEventListener(<span class="keyword">type</span>, fn, <span class="literal">false</span>);</span><br><span class="line">    &#125;;</span><br><span class="line">&#125; <span class="keyword">else</span> <span class="keyword">if</span> (<span class="keyword">typeof</span> <span class="built_in">document</span>.attachEvent === <span class="string">&#x27;function&#x27;</span>) &#123; <span class="comment">// IE</span></span><br><span class="line">    utils.addListener = <span class="function"><span class="keyword">function</span> (<span class="params">el, <span class="keyword">type</span>, fn</span>) </span>&#123;</span><br><span class="line">        el.attachEvent(<span class="string">&#x27;on&#x27;</span> + <span class="keyword">type</span>, fn);</span><br><span class="line">    &#125;;</span><br><span class="line">    utils.removeListener = <span class="function"><span class="keyword">function</span> (<span class="params">el, <span class="keyword">type</span>, fn</span>) </span>&#123;</span><br><span class="line">        el.detachEvent(<span class="string">&#x27;on&#x27;</span> + <span class="keyword">type</span>, fn);</span><br><span class="line">    &#125;;</span><br><span class="line">&#125; <span class="keyword">else</span> &#123; <span class="comment">// older browsers</span></span><br><span class="line">    utils.addListener = <span class="function"><span class="keyword">function</span> (<span class="params">el, <span class="keyword">type</span>, fn</span>) </span>&#123;</span><br><span class="line">        el[<span class="string">&#x27;on&#x27;</span> + <span class="keyword">type</span>] = fn;</span><br><span class="line">    &#125;;</span><br><span class="line">    utils.removeListener = <span class="function"><span class="keyword">function</span> (<span class="params">el, <span class="keyword">type</span>, fn</span>) </span>&#123;</span><br><span class="line">        el[<span class="string">&#x27;on&#x27;</span> + <span class="keyword">type</span>] = <span class="literal">null</span>;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>说到这里，要特别提醒一下关于浏览器探测的事情。当你使用这个模式的时候，不要对浏览器特性过度假设。举个例子，如果你探测到浏览器不支持window.addEventListener，不要假设这个浏览器是IE，也不要认为它不支持原生的XMLHttpRequest，虽然这个结论在整个浏览器历史上的某个点是正确的。当然，也有一些情况是可以放心地做一些特性假设的，比如.addEventListener和.removeEventListerner，但是通常来讲，浏览器的特性在发生变化时都是独立的。最好的策略就是分别探测每个特性，然后使用条件初始化，使这种探测只做一次。</strong></p>]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;strong&gt;callback&lt;/strong&gt;&lt;br&gt;一个回调的例子&lt;/p&gt;
&lt;p&gt;我们从一个例子开始，首先介绍无回调的情况，然后在作修改。假设你有一个通用的函数，用来完成某种复杂的逻辑并返回一大段数据。假设我们用findNodes()来命名这个通用函数，这个函数用来对DOM树进行遍历，并返回我所感兴趣的页面节点：&lt;/p&gt;
&lt;figure class=&quot;highlight actionscript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; findNodes = &lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; i = &lt;span class=&quot;number&quot;&gt;100000&lt;/span&gt;, &lt;span class=&quot;comment&quot;&gt;// big, heavy loop&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        nodes = [], &lt;span class=&quot;comment&quot;&gt;// stores the result&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        found; &lt;span class=&quot;comment&quot;&gt;// the next node found&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; (i) &amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        i -= &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        &lt;span class=&quot;comment&quot;&gt;// complex logic here...&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;        nodes.push(found);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; nodes;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="javascript" scheme="http://landerqi.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>一本书读懂财报</title>
    <link href="http://landerqi.com/2018/09/04/%E4%B8%80%E6%9C%AC%E4%B9%A6%E8%AF%BB%E6%87%82%E8%B4%A2%E6%8A%A5/"/>
    <id>http://landerqi.com/2018/09/04/一本书读懂财报/</id>
    <published>2018-09-04T09:34:05.000Z</published>
    <updated>2019-07-02T06:28:51.122Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="在会计眼中企业都在忙些什么">在会计眼中，企业都在忙些什么？</span></h3><blockquote><p>日子就这样一天天地过，企业就这样一天天地经营、投资、融资。</p></blockquote><span id="more"></span><h4><span id="流动资产包含哪些项目">流动资产包含哪些项目？</span></h4><blockquote><p>__货币资金（Cash）__：包括库存现金、银行存款和其他货币资金三个项目的期末余额，具有专门用途的货币资金不包括在内。</p></blockquote><blockquote><p>__应收账款（Accounts Receivable）__：核算企业因销售商品、提供劳务等经营活动应收取的款项。</p></blockquote><blockquote><p>__其他应收款（Other Receivables）__：企业除存出保证金（如租房子时交付的未来将退回的保证金、押金等）、买入返售金融资产、应收票据、应收账款、预付账款、应收股利、应收利息、应收代位追偿款、应收分保账款、应收分保合同准备金、长期应收款等以外的其他各种应收及暂付款项。</p></blockquote><blockquote><p>__预付账款（Prepaid Accounts）__：企业按照合同规定预付的款项。</p></blockquote><blockquote><p>__在产品（Work in Process）__：正在加工，尚未完成的产品。有广狭二义：广义的包括正在加工的产品和准备进一步加工的半成品，狭义的仅指正在加工的产品。产成品（Finished Goods）：企业已经完成全部征税过程并已验收入库合乎标准规格和技术条件，可以按照合同规定的条件送交订货单位，或者可以作为商品对外销售的产品。存货（Inventory）：企业在日常活动中持有以备出售的产成品或商品、处在生产过程中的在产品、在生产过程或提供劳务过程中耗用的材料和物料等。</p></blockquote><blockquote><p>其实，资产和费用之间有一个很大的共同之处，就是都得花钱。但如果这笔钱可以换来一个对将来有用的东西，那它就是资产。如果这笔钱花完就完了，那它就是费用。而这6万元换来了一批能使用6个月的办公用品，所以这是一项对未来有用的支出，它符合资产的一般概念，所以它是一项资产。<br><br>但这批办公用品无疑会在6个月之内用光，这6万元最终将会变成小张公司这6个月的办公费用。它最初的确是一笔资产，但随着企业的正常运营和时间的流逝，它最终变成了一笔费用，这就叫待摊费用。比如预付的房租、预付的广告费用，甚至开办一家企业所需要的开办费，都是待摊费用。</p></blockquote><blockquote><p>__流动资产（Current Assets）__：指企业可以在一年或者超过一年的一个营业周期内变现或者运用的资产。非流动资产（Non-current Assets）：指流动资产以外的资产。</p></blockquote><h4><span id="非流动资产是什么">非流动资产是什么？</span></h4><blockquote><p>__长期投资（Long-term Investments）__：指不满足短期投资条件的投资，即不准备在一年或长于一年的经营周期之内转变为现金的投资。长期投资按其性质分为长期股票投资、长期债券投资和其他长期投资。</p></blockquote><blockquote><p>__固定资产（Fixed Assets）__：指同时具有下列特征的有形资产：（1）为生产商品、提供劳务、出租或经营管理而持有的；（2）使用寿命超过一个会计年度。</p></blockquote><blockquote><p>__固定资产的折旧（Depreciation）__：指一定时期内为弥补固定资产损耗按照规定的固定资产折旧率提取的固定资产折旧，或按国民经济核算统一规定的折旧率虚拟计算的固定资产折旧。</p></blockquote><blockquote><p>__土地使用权（Land Usage Rights）__：国家机关、企事业单位、农民集体和公民个人，以及三资企业，凡具备法定条件者，依照法定程序或依约定对国有土地或农民集体土地所享有的占有、利用、收益和有限处分的权利。</p></blockquote><blockquote><p>__无形资产（Intangible Assets and Other Assets）__：指企业拥有或者控制的没有实物形态的可辨认非货币性资产。本科目核算企业持有的无形资产成本，包括专利权、非专利技术、商标权、著作权、土地使用权等。</p></blockquote><h4><span id="孤立的资产怎么组成鲜活的企业">孤立的资产怎么组成鲜活的企业？</span></h4><blockquote><p>所以一般情况下，会计们把公鸡叫存货，而把母鸡归入生产性生物资产这一项。生物资产（Biological Assets）：指有生命的动物和植物。生物资产分为消耗性生物资产、生产性生物资产和公益性生物资产。</p></blockquote><h4><span id="资产如何计价">资产如何计价？</span></h4><blockquote><p>__历史成本/原始成本/实际成本（Historical Cost）__：资产在其取得时为它所支付的现金或现金等价物的金额。负债在正常经营活动中为交换而收到的或为偿付将要支付的现金或现金等价物的金额。</p></blockquote><blockquote><p>__金融资产（Financial Assets）__：金融资产通常指企业的库存现金、银行存款、其他货币资金（如：企业的外埠存款、银行本票存款、银行汇票存款、信用卡存款、信用证保证金存款、存出投资款等）、应收账款、应收票据、贷款、其他应收款、股权投资、债权投资和衍生金融工具形成的资产等。</p></blockquote><blockquote><p>__公允价值/公允市价/公允价格（Fair Value）__：熟悉市场情况的买卖双方在公平交易的条件下和自愿的情况下所确定的价格，或无关联的双方在公平交易的条件下一项资产可以被买卖或者一项负债可以被清偿的成交价格。</p></blockquote><blockquote><p>也就是说，除了金融资产与房地产之外，所有的大多数资产都是按照历史成本来计价。</p></blockquote><h4><span id="历史成本有哪些含义">历史成本有哪些含义？</span></h4><blockquote><p>还有一个例子。一个公司把自己的一项资产卖出去了，过了一个星期，它又把它买回来了。这家公司的老板可没有笨到给自己找麻烦，他显然另有目的。这是因为，在历史成本计价体系之下，只要没有新的交易发生，资产的价值只能减少不能增加（按照公允价值计价的金融资产和投资性房地产除外），而这家企业重新买回已经卖掉的资产，就可以按照买回交易中的价格重新记录资产的价值。可见，在历史成本的计价体系下，增加资产价值的唯一途径是发生一个新的交易，这是历史成本原则的第二层含义。</p></blockquote><h4><span id="有多少负债要还">有多少负债要还？</span></h4><blockquote><p>__负债（Liability）__：由于过去的交易或事项所引起的公司、企业的现有债务，这种债务需要企业在将来以转移资产或提供劳务加以清偿，从而引起未来经济利益的流出。</p></blockquote><blockquote><p>__短期借款（Short-term Borrowing）__：企业用来维持正常的生产经营所需的资金或为抵偿某项债务而向银行或其他金融机构等外单位借入的、还款期限在一年以下或者一年的一个经营周期内的各种借款。</p></blockquote><blockquote><p>__长期借款（Long-term Loans Payable）__：企业从银行或其他金融机构借入的期限在一年以上（不含一年）的借款。</p></blockquote><blockquote><p>__应付账款（Accounts Payable）__：企业因购买材料、物资和接受劳务供应等而应该付给供货单位的账款。<strong>其他应付款（Other Payables）</strong>：企业在商品交易业务以外发生的应付和暂收款项。指企业除应付票据、应付账款、应付工资、应付利润等以外的应付、暂收其他单位或个人的款项。</p></blockquote><blockquote><p><strong>预收账款（Deposit Received）</strong>：买卖双方协议商定，由购货方预先支付一部分货款给供应方而发生的一项负债。</p></blockquote><blockquote><p><strong>流动负债</strong>是指企业在一年之内必须支付的负债。那么，我们现在再来看一看非流动负债。</p></blockquote><blockquote><p><strong>应付债券（Bond Payable）</strong>：企业为筹集资金而对外发行的期限在一年以上的长期借款性质的书面证明，约定在一定期限内还本付息的一种书面承诺。</p></blockquote><blockquote><p>在应付债券下面，还有一项负债，叫作“长期应付款”。一般情况下，长期应付款会跟一种交易有关，比如说租赁。在会计看来，租赁分为两种，即经营性租赁和融资性租赁。如果租赁期限比较长、涉及的金额比较大，那这种租赁就属于融资性租赁；反之则是经营性租赁。如果是经营性租赁，则承租者未购买租赁物，只需向出租者支付租金即可。相应的，租入的资产不属于承租方，不在承租方的报表上出现，未来将要支付的租金也只需在支付时记入相应的费用。但融资性租赁的情况则完全不同，在会计看来，进行融资性租赁的企业其实是在用分期付款的方式购买一项资产，所谓的租金就是分期付款的款项。相应的，租入的资产被认为是承租方的资产，因此可以出现在报表上，未来将要支付的租金的总额也要在签署租赁合约时记入负债，这就是长期应付款。综上所述，经营性租赁是一种表外业务，即相应的资产和负债都不出现在报表上，而融资租赁则是一种表内业务。长期应付款（Long-term Payable）：企业除了长期借款和应付债券以外的长期负债，包括应付引进设备款、应付融资租入固定资产的租赁费等。</p></blockquote><blockquote><p><strong>流动负债（Current Liabilities）</strong>：在一份资产负债表中，一年内或者超过一年的一个营业周期内需要偿还的债务合计。流动负债主要包括短期借款、应付票据、应付账款、预收账款、应付工资、应付福利费、应付股利、应交税金、其他暂收应付款项、预提费用和一年内到期的长期借款等。非流动负债（Non-current Liabilities）：偿还期在一年或者超过一年的一个营业周期以上的债务。非流动负债的主要项目有长期借款、应付债券和长期应付款等。</p></blockquote><h4><span id="股东都有些什么权益">股东都有些什么权益？</span></h4><blockquote><p><strong>股东权益（Shareholder’s Equity）</strong>：公司总资产中扣除负债所余下的部分，也称为净资产。股东权益是一个很重要的财务指标，它反映了公司的自有资本。</p></blockquote><blockquote><p><strong>股本（Capital Stock）</strong>：股东在公司中所占的权益，多用于指股票。</p></blockquote><blockquote><p>于是，会计们将小黄投入的100万元当作股本，将小张投入的500万元中的100万元也当作股本，而剩下的400万元则被放入资本公积里。也就是说，当公司有多个股东的时候，不是以他们的投资额来确定股权比例，而是以他们在股本中所占的比例确定股权比例。值得说明的是，放在资本公司的400万元可不是小张独有的，它是所有股东共有的。也就是说，小张拥有400万元资本公积中的200万元，小黄也同样拥有200万元。换句话说，小张刚刚投进来的500万元，瞬间就变成了300万元，小张也因此损失了200万元。真是奇怪了，既然如此，小张为什么还要做这赔本的买卖呢？显然在小张看来，只要丢掉这200万元，就能换来小黄公司50%的股权，相当值得。这种情况通常发生在投资者对被投资公司的未来收益看好的前提之下。</p></blockquote><blockquote><p><strong>资本公积（Additional Paid-in Capital）</strong>：企业收到的投资者的超出其在企业注册资本所占份额，以及直接记入所有者权益的利得和损失等。资本公积包括资本溢价（股本溢价）和直接记入所有者权益的利得和损失等。</p></blockquote><blockquote><p>这一部分也被放在两个项目里来计算，一个项目是盈余公积，另一个项目是未分配利润。简单说来，盈余公积是法律不让我们分配的利润，而未分配利润是企业自己不想分的利润。</p></blockquote><blockquote><p>__盈余公积（Surplus Zeserve）__：企业按照规定从净利润中提取的各种积累资金。</p></blockquote><blockquote><p>__未分配利润（Retained Earnings）__：企业未作分配的利润。它在以后年度可继续进行分配，在未进行分配之前，属于所有者权益的组成部分。</p></blockquote><h4><span id="资产负债表透露了什么信息">资产负债表透露了什么信息？</span></h4><blockquote><p>只有第二个等式，即“股东权益=资产-负债”是成立的。</p></blockquote><blockquote><p>一个公司必须给银行还了债、给供应商付了款、给员工发了工资、给税务局交了税之后，才能把剩下来的东西分给股东，这叫作股东的“剩余求偿权”。</p></blockquote><h4><span id="获取利润的第一步是什么">获取利润的第一步是什么？</span></h4><blockquote><p><strong>营业税（Business Tax）</strong>：国家对工商营利事业按营业额征收的税，属于流转课税的一类。营业税金及附加（Business Tax and Surcharges）：企业经营活动应负担的相关税费，包括营业税、消费税、城市维护建设税、资源税和教育费附加等。企业应通过“营业税金及附加”科目，核算企业经营活动相关税费的发生和结转情况。</p></blockquote><blockquote><p>但是营业税又与增值税不同，前者是一种价内税，而后者是价外税。价内税（Tax Included in Price）：税金包含在商品价值或价格之内的税。价外税（Tax Excluded in Price）：税款不包含在商品价格内的税，价税分列的税种。</p></blockquote><blockquote><p><strong>增值税（Value-added Tax）</strong>：一种销售税，是消费者承担的税费，属累退税，是基于商品或服务的增值而征税的一种间接税，增值税征收通常包括生产、流通或消费过程中的各个环节，是基于增值额或价差为计税依据的中性税种</p></blockquote><blockquote><p><strong>费用（Expense）</strong>：一般用于描述公司为销售而发生的各种成本支出、杂项管理、利息、税金，以及其他影响利润表的项目。</p></blockquote><blockquote><p><strong>营业费用（Operating Expenses）</strong>：公司销售、杂项与管理费用的同义词。</p></blockquote><blockquote><p><strong>管理费用（General and Administrative Expense）</strong>：企业的行政管理部门为管理和组织经营而发生的各项费用。</p></blockquote><blockquote><p><strong>财务费用（Financing Expense）</strong>：企业在生产经营过程中为筹集资金而发生的各项费用。包括企业生产经营期间发生的利息支出（减利息收入）、汇兑净损失（有的企业如商品流通企业、保险企业进行单独核算，不包括在财务费用中）、金融机构手续费，以及筹资发生的其他财务费用如债券印刷费、国外借款担保费等。</p></blockquote><h4><span id="获取利润的第三步是什么">获取利润的第三步是什么？</span></h4><blockquote><p><strong>投资收益（Investment Income）</strong>：对外投资所取得的利润、股利和债券利息等收入减去投资损失后的净收益。</p></blockquote><blockquote><p><strong>资产减值损失（Impairment Loss of Assets Impairment）</strong>：因资产的账面价值高于其可收回金额而造成的损失。会计准则规定资产减值范围主要是固定资产、无形资产以及除特别规定外的其他资产减值的处理。公允价值变动收益（Gains on the Changes in the Fair Value）：以公允价值计量且其变动记入当期损益的交易性金融资产。在资产负债表日，“交易性金融资产”的公允价值高于其账面价值的差额，应借记“交易性金融资产－公允价值变动”，贷记“公允价值变动损益”，公允价值低于其账面价值的差额，则做相反的分录。</p></blockquote><blockquote><p>“营业收入-营业成本-营业税金及附加-营业费用-管理费用-财务费用-资产减值的损失+公允价值变动的收益+投资收益=企业的营业利润”。</p></blockquote><blockquote><p><strong>营业利润（Operating Profit）</strong>：企业利润的主要来源，主要由营业收入、营业成本、期间费用、资产减值损失、公允价值变动净收益、投资净收益构成。</p></blockquote><h4><span id="获取利润的第四步是什么">获取利润的第四步是什么？</span></h4><blockquote><p><strong>营业外收入（Non-operating Revenues）</strong>：除企业营业执照中规定的主营业务以及附属的其他业务之外的所有收入即营业外收入。营业外收入主要包括：非流动资产处置利得、非货币性资产交换利得、出售无形资产收益、债务重组利得、企业合并损益、盘盈利得、因债权人原因确实无法支付的应付款项、政府补助、教育费附加返还款、罚款收入、捐赠利得等。营业外支出（Non-operating Expenses）：企业发生的与企业日常生产经营活动无直接关系的各项支出。包括非流动资产处置损失、非货币性资产交换损失、债务重组损失、公益性捐赠支出、非常损失、盘亏损失等。</p></blockquote><h4><span id="获取利润的最后一步是什么">获取利润的最后一步是什么？</span></h4><blockquote><p>到这里基本可以计算出一家企业在一定时间内到底赚到了多少钱：“营业利润+营业外的收入-营业外的支出+补贴收入+汇兑损益（视该企业是否有外贸业务而定）=利润总额”；而“利润总额-所得税=企业净利润”，企业净利润即是企业所赚到的钱。</p></blockquote><blockquote><p><strong>净利润（Net Profit）</strong>：在利润总额中按规定交纳了所得税以后公司的利润留存，一般也称为税后利润或净收入。净利润是一个企业经营的最终成果：净利润多，企业的经营效益就好；净利润少，企业的经营效益就差，它是衡量一个企业经营效益的主要指标。</p></blockquote><blockquote><p><strong>应纳税所得（Taxable Income）</strong>：收入扣除成本、费用等之后的纯收益，纳税人取得任何一项所得，都有相应的消耗和支出，应予以扣除。只有企业取得的所得扣除为取得这些所得而发生的成本费用支出后的余额，才是企业所得税的应税所得。应税利润（Taxable Profit）：根据税法规定所确认的收入总额与准予扣除项目金额（即可扣除的费用）的差额，又称为应纳税所得额，是企业应纳所得税的计税依据。</p></blockquote><blockquote><p>这样就产生了净利润小于利润总额75%的情况。因此，用利润总额乘以75%并不能作为计算净利润的方法，要得到净利润，只能用利润总额减去所得税的方式得到。</p></blockquote><h4><span id="第二张财务报表是什么">第二张财务报表是什么？</span></h4><blockquote><p>资产负债表是一个时点的概念，而利润表则是一个时段的概念</p></blockquote><h4><span id="对于新公司来说什么才是头等大事">对于新公司来说，什么才是头等大事？</span></h4><blockquote><p><strong>资产=负债+股东权益</strong></p></blockquote><h4><span id="为什么会有人做赔本的买卖">为什么会有人做赔本的买卖？</span></h4><blockquote><p><strong>变动成本（Variable Cost）</strong>：那些总额在相关范围内随着业务量的变动而呈线性变动的成本。直接材料是典型的变动成本，在一定期间内它们的发生总额随着业务量的增减而成正比例变动，但单位产品的耗费则保持不变。固定成本（Fixed Cost）：总额在一定时期和一定业务量范围内，不受业务量增减变动影响而能保持不变的成本。</p></blockquote><h4><span id="固定成本搞出了什么乱子">固定成本“搞出”了什么乱子？</span></h4><p><strong>有意思</strong></p><blockquote><p>因此，不能简单地把毛利润增加看成业绩提升的表现。事实上，毛利润的提升不一定由业绩提升引起，还有可能是因为产成品库存增加。</p></blockquote><h4><span id="研究支出对财务报表做了什么">研究支出对财务报表做了什么？</span></h4><blockquote><p>首先，会计准则规定：企业的研究支出应被记录在管理费用当中；其次，产品开发阶段的投入，如果满足一定条件的话，可以被记录在无形资产当中。</p></blockquote><blockquote><p>所以说，企业通过自己的研究获得的技术，如果不申请专利，不会得到半点在无形资产这一项上体现的机会；我们在报表上看到的那些技术，多半是买别人的。</p></blockquote><blockquote><p>因此，会计准则虽然对研究支出规定了唯一的记录方式，但企业却能够通过设计不同的组织结构，来实现不同的会计结果。</p></blockquote><h4><span id="财务报表怎样诞生">财务报表怎样诞生？</span></h4><blockquote><p>表3 新设立公司的资产负债表[插图]附：该新成立公司进行的13项经济活动1.设立公司，股东投资3200万元现金。2.向银行借款5100万元，借款期限为6个月。3.购买生产设备、办公家具和车辆，建造办公楼、厂房，花费5700万元，以银行存款支付。4.获取一块土地的使用权，花费150万元。5.采购原材料花费2400万元，到12月31日为止支付1600万元现金，其余部分将在下一年度分期支付。6.生产出一批产品。产品成本为3600万元，其中使用的原材料价值为2400万元；发生了人工费和其他支出1200万元，以现金支付。7.销售产品4300万元，销售成本3100万元。到12月31日为止收到3000万元现金，其余部分将在下一年度内收到。8.为下一年采购原材料预付150万元。9.研发部门当期花费50万元成功地研制出用低成本进行污染处理的技术。10.支付管理人员工资和行政开支150万元，支付销售人员工资和外地销售分公司开支250万元。11.支付银行利息130万元。12.支付所得税100万元。13.分配现金股利100万元。</p></blockquote><h4><span id="资产负债表与利润表之间有什么关系">资产负债表与利润表之间有什么关系？</span></h4><blockquote><p>资产负债表表示了一个时间点的概念，而利润表则是一张反映时间段的报表。</p></blockquote><h4><span id="现金流量表的真相是什么">现金流量表的真相是什么？</span></h4><blockquote><p>经营、投资、融资。现金流量表怎么做呢？它就是从经营、投资和融资三个角度，对现金的流入和流出进行了描述。</p></blockquote><blockquote><p><strong>现金流量表（Cash Flow Statement）</strong>：反映企业在一定会计期间现金和现金等价物流入和流出的报表。现金，是指企业库存现金以及可以随时用于支付的存款。现金等价物，是指企业持有的期限短、流动性强、易于转换为已知金额现金、价值变动风险很小的投资。</p></blockquote><h4><span id="一家公司的现金是怎样流入和流出的">一家公司的现金是怎样流入和流出的？</span></h4><blockquote><p>__退税（Tax Rebate）__：国家按规定对纳税人已纳税款的退还，优惠退税是税收支出的一种形式，即国家为鼓励纳税人从事或扩大某种经济活动而给予的税款退还。通常包括出口退税、再投资退税、复出口退税、溢征退税等多种形式。</p></blockquote><blockquote><p>企业的投资无非有两种：一种是一家企业自己投给自己的，也即对内投资，这笔投资会形成这家公司的固定资产和无形资产；还有一种，是这家公司投资给别家公司的，比如购买别人的股票或者债券，或者组建一家子公司或合资企业，这是一种对外的投资。但无论是对内投资还是对外投资，只要是投资，就一定会出现现金的流出，这就是投资活动的现金流出。</p></blockquote><blockquote><p>对于企业来说，其融资方式也只有两种类型：一种是债务融资，一种是股权融资。但无论是债务融资还是股权融资，在它融资的时候一定会有现金流入。但融资活动的现金流入一定伴随着一定量的现金流出。比如进行债务融资，企业需要向银行还本付息；再比如进行股权融资，企业就需要给股东分红。</p></blockquote><h4><span id="现金流量表为什么存在">现金流量表为什么存在？</span></h4><blockquote><p>企业当然最希望现金大多从经营活动流入，因为源自经营活动的流入一般是可以长久持续下去的。而在各种不同类型的流出中，企业最喜欢的是投资，因为投资的现金流出很可能在某一日创造出收益。这就是为什么在了解现金的增减变化情况之外，还必须了解增减变化的原因，这也就是为什么企业需要一张现金流量表的原因。</p></blockquote><h4><span id="现金流量表是怎样产生的">现金流量表是怎样产生的？</span></h4><blockquote><p>这项活动一定会造成现金的流出，但它到底是什么样的现金流出呢？如果说，这笔资金能为企业带来收益，那它一定是投资活动的现金流出；可技术研究却未必有成果，也就未必能为企业带来利润，因此，它其实也是一项经营活动的现金流出。</p></blockquote><blockquote><p>—属于经营活动、投资活动还是融资活动，会造成现金的流入还是流出</p></blockquote><blockquote><p>__经营活动现金流量（Cash from Operating Activities）__：企业投资活动和筹资活动以外的所有的交易和事项产生的现金流量。它是企业现金的主要来源。经营活动现金流入的主要项目包括：（1）销售商品、提供劳务收到的现金；（2）收到的各种税费；（3）收到的其他与经营活动有关的现金。经营活动现金流出的主要项目包括：（1）购买商品、接受劳务支付的现金；（2）支付给职工以及为职工支付的现金；（3）支付的各项税费；（4）支付的其他与经营活动有关的现金。</p></blockquote><blockquote><p>__投资活动现金流量（Cash from Investing Activities）__：企业长期资产（通常指一年以上）的购建及其处置产生的现金流量，包括购建固定资产、长期投资现金流量和处置长期资产现金流量，并按其性质分项列示。主要包括以下项目：（1）“收回投资所收到的现金”项目，反映企业出售、转让或到期收回除现金等价物以外的短期投资、长期股权投资而收到的现金，以及收回长期债权投资本金而收到的现金。不包括长期债权投资收回的利息，以及收回的非现金资产。（2）“取得投资收益所收到的现金”项目，反映企业因各种投资而分得的现金股利、利润、利息等。（3）“处置固定资产、无形资产和其他长期资产而收到的现金净额”项目，反映企业处置固定资产、无形资产和其他长期资产所取得的现金，扣除为处置这些资产而支付的有关费用后的净额。由于自然灾害所造成的固定资产等长期资产损失而收到的保险赔偿收入，也在本项目反映。（4）“收到的其他与投资活动有关的现金”项目，反映企业除了上述各项以外，收到的其他与投资活动有关的现金流入。其他现金流入如价值较大的，应单列项目反映。（5）“购建固定资产、无形资产和其他长期资产所支付的现金”项目，反映企业购买、建造固定资产，取得无形资产和其他长期资产所支付的现金，不包括为购建固定资产而发生的借款利息资本化的部分，以及融资租入固定资产支付的租赁费，借款利息和融资租入固定资产支付的租赁费，在筹资活动产生的现金流量中单独反映。企业以分期付款方式购建的固定资产，其首次付款支付的现金作为投资活动的现金流出，以后各期支付的现金作为筹资活动的现金流出。（6）“投资所支付的现金”项目，反映企业进行各种性质的投资所支付的现金，包括企业取得的除现金等价物以外的短期股票投资、长期股权投资支付的现金、长期债券投资支付的现金，以及支付的佣金、手续费等附加费用。</p></blockquote><blockquote><p>__融资活动现金流量（Cash from Financing Activities）__：指导致企业资本及债务的规模和构成发生变化的活动所产生的现金流量。（1）“吸收投资所收到的现金”项目，反映企业收到的投资者投入的现金，包括以发行股票方式筹集的资金实际收到股款净额（发行收入减去支付的佣金等发行费用后的净额）、发行债券实际收到的现金（发行收入减去支付的佣金等发行费用后的净额）等。（2）“借款所收到的现金”项目，反映企业举借各种短期、长期借款所收到的现金。（3）“收到的其他与筹资活动有关的现金”项目，反映企业除上述各项目外，收到的其他与筹资活动有关的现金流入，如接受现金捐赠等。（4）“偿还债务所支付的现金”项目，反映企业以现金偿还债务的本金，包括偿还金融企业的借款本金、偿还债券本金等。企业偿还的借款利息、债券利息，在“偿债利息所支付的现金”项目中反映，不包括在本项目内。（5）“分配股利、利润和偿还利息所支付的现金”项目，反映企业实际支付的现金股利、利润，以及支付给其他投资的利息。（6）“支付的其他与筹资活动有关的现金”项目，反映企业除了上述各项外，支付的其他与筹资活动有关的现金流出，如捐赠现金支出等。其他现金流出如价值较大的，单独列项目反映。</p></blockquote><p><strong>所以说现金流量表更能反映一家企业的经营状况～利润表有太多方式可以润饰了</strong></p><blockquote><p>它的经营活动现金流又是多少呢？答案是-500万元。看上去，它好像是亏损了；但我们又清楚地记得，它不仅是赚钱的，而且在新公司里面，它的盈利能力还算是不错的。因此，这家经营活动现金流为-500万元的公司实际上是一家正在盈利的公司，这再度验证了，净利润和现金流完全是两码事，完全可以一个为正、一个为负。但这到底是怎么回事呢？真有些丈二和尚摸不着头脑。</p></blockquote><h4><span id="为什么每家企业都需要这三张财务报表">为什么每家企业都需要这三张财务报表？</span></h4><p><strong>我应该会更关注现金流量表和利润表～</strong></p><blockquote><p>在第一个维度上，现金流量表描述了一家企业能否生存下去，即所谓风险的视角；在第二个维度上，资产负债表和利润表则展示了倘若这家企业能够继续生存它将是什么样子——有多少家底，又有多少收益——即所谓收益的视角。</p></blockquote><h4><span id="银行家和投资专家最爱哪张报表">银行家和投资专家最爱哪张报表？</span></h4><blockquote><p>实际上，购买一家公司相当于购买了它的股东权益，因为收购使你取代了原有股东而成为这个公司的新股东，所以你买下的是股东权益。既然成为这家公司的新股东，显然，你最该关注股东权益，而关注股东权益当然就要关注资产负债表了。由于“股东权益=资产-负债”永恒成立，购买股东权益也就意味着同时购买了这家公司的资产与负债。购买资产也就罢了，购买负债是一种难以想象的行为，可不是嘛，谁会购买负债啊？可实际上，收购公司时你就买了那家公司的负债。不用花钱就能获得一家公司，就是所谓的零成本收购，显然是痴人说梦，除非……除非购买者还同时承担了这家公司的所有负债。</p></blockquote><h4><span id="收购时资产和负债谁更危险">收购时，资产和负债谁更“危险”？</span></h4><blockquote><p>当然，造成负债没有出现在报表上的原因多种多样，或有负债的存在便是其一。什么是或有负债呢？比如说，A公司向B公司借了500万元，而你要收购的这家C公司恰好为B公司做了担保，C公司也就同时背上了一笔或有负债。在这种情况下，要是A公司“跑路”，C公司就得代A公司向B公司偿还这笔债务；但如果A公司按时还了债，C公司自然可以高枕无忧。因此，那些无法确定是否存在的负债，就是所谓的或有负债。</p></blockquote><h4><span id="怎么做同型分析">怎么做同型分析？</span></h4><blockquote><p>同型分析。使所有的项目都除以收入，再乘以100%，就能获得这些项目在收入中的占比，也就得到了同型分析的结果（见表6）：营业成本为3100万元，占收入的72%；营业费用、管理费用和财务费用占收入的比重分别是6%、5%和3%；营业利润所占的比重为14%，在扣除了2%的所得税之后，净利润在收入中的占比达到了12%。表6 利润表及其同型分析[插图]这是一张进行了同型分析的报表，它让我们更直观地了解了利润表的结构。因为营业成本占收入的72%，营业费用、管理费用和财务费用又共同占据收入14%的比例，再加上2%的所得税，这就是为什么这家公司的营业收入就只有12%能够转化为利润的原因。</p></blockquote><blockquote><p>流动资产一共占这家公司资产总额的39%；与此同时，无形资产又占了2%的比重；余下的固定资产所占比例则达到60%。一家固定资产占比如此之大的企业，想必是一家制造业的企业。另外，这家公司的应收账款竟然占资产总额的14%，这是一个相当大的比重，所以这家公司的产品应该没那么好卖，它或许正面临着巨大的竞争和来自同行的挑战。</p></blockquote><blockquote><p>__趋势分析（Trend Analysis）__：将实际达到的结果，与不同时期财务报表中同类指标的历史数据进行比较，从而确定财务状况、经营成果和现金流量的变化趋势和变化规律的一种分析方法。比较分析（Comparing Analysis）：通过两个或两个以上相关经济指标的对比，确定指标间的差异，并进行差异分析或趋势分析的一种分析方法。</p></blockquote><h4><span id="怎样用比率分析企业的盈利能力">怎样用比率分析企业的盈利能力？</span></h4><blockquote><p>__毛利率（Gross Margin）__：毛利与销售收入（或营业收入）的百分比，其中毛利是营业收入和与收入相对应的营业成本之间的差额。<br><br>  __净利润率（Net Profit Margin）__：又称销售净利率，是反映公司盈利能力的一项重要指标，是扣除所有成本、费用和企业所得税后的利润率。</p></blockquote><blockquote><p>我们都知道，企业无论从事怎样的经济活动，都可以被抽象为在周而复始进行着从现金开始再到现金的循环：企业股东投入的资金，随着企业正常的运营，被转化为各种各样的资产形式；随着企业售出产品，企业最终又通过这些资产赚到了钱。</p></blockquote><blockquote><p>在同样的时间里，总资产的周转率越高，完成上述循环的次数越多，赚的钱也就越多。因此，总资产的周转率是一个与效率有关的概念。判断一家企业的盈利能力如何，不仅要立足于效益，更要立足于效率。如果满脑子只有毛利率、净利润率这样的效益因素显然是不够的，还必须要牢记周转率这样的效率因素，这样才能对企业的利润有一个全面的考量。</p></blockquote><blockquote><p>[插图]即效率×效益=总资产报酬率，效率、效益和投资回报之间的关系一目了然。无论是效率还是效益发生改变，都将影响企业的投资回报。</p></blockquote><blockquote><p>__总资产报酬率（Return on Assets）__：又称总资产利润率、总资产回报率、资产总额利润率，英文缩写ROA，用以评价企业运用全部资产的总体获利能力。</p></blockquote><blockquote><p>此外，用净利润除以股东权益，股东们就会对自己的投资回报了然于胸。净利润是股东投资所获得的回报，股东权益是股东自己的投资，二者相除得到的就是股东权益报酬率。但实际上，会计们并不把它称作股东权益报酬率，而把它叫作净资产报酬率。因为“股东权益=总资产-负债”，而股东权益也被称作净资产，即净剩下来归股东所有的资产，可见把股东权益报酬率称为净资产报酬率一点也不奇怪。</p></blockquote><blockquote><p>__投资回报率（Return on Investment）__：英文缩写ROI，通过投资而应返回的价值，企业从一项投资性商业活动的投资中得到的经济回报。<br><br>  __净资产收益率（Return on Equity）__：又称净资产利润率，英文缩写ROE，指利润额与平均股东权益的比值。该指标越高，说明给股东（所有者）带来的收益越高；该指标越低，说明企业股东（所有者）的获利能力越弱。该指标体现了自有资本获得净收益的能力。</p></blockquote><h4><span id="什么是企业的营运能力">什么是企业的营运能力？</span></h4><blockquote><p>一般来说，用收入除以某项资产得到该资产的周转率</p></blockquote><blockquote><p>__总资产周转率（Total Assets Turnover）__：企业在一定时期业务收入净额同平均资产总额的比率。总资产周转率是综合评价企业全部资产的经营质量和利用效率的重要指标。周转率越大，说明总资产周转越快，反映出销售能力越强。<br><br>  __应收账款周转率（Accounts Receivable Turnover）__：在一定时期内（通常为一年）应收账款转化为现金的平均次数。应收账款周转率是销售收入除以平均应收账款的比值，也就是年度内应收账款转为现金的平均次数，它说明应收账款流动的速度。用时间表示的周转速度是应收账款周转天数，也叫平均应收账款回收期或平均收现期，表示企业从取得应收账款的权利到收回款项、转换为现金所需要的时间，等于365除以应收账款周转率。<br><br>  __流动资产周转率（Current Assets Turnover）__：销售收入与流动资产平均余额的比率，它反映的是全部流动资产的利用效率。流动资产周转率是分析流动资产周转情况的一个综合指标，流动资产周转得快，可以节约资金，提高资金的利用效率。<br><br>  __固定资产周转率（Fixed Assets Turnover）__：企业年产品销售收入净额与固定资产平均净值的比率。它是反映企业固定资产周转情况，从而衡量固定资产利用效率的一项指标。该比率越高，表明固定资产利用效率高，利用固定资产效果好。<br><br>  __存货周转率（Inventory Turnover）__：企业一定时期主营业务成本与平均存货余额的比率。用于反映存货的周转速度，即存货的流动性及存货资金占用量是否合理，促使企业在保证生产经营连续性的同时，提高资金的使用效率，增强企业的短期偿债能力。</p></blockquote><blockquote><p>__营运能力（Operating Capability）__：企业的经营运行能力，即企业运用各项资产以赚取利润的能力。企业营运能力的财务分析比率为各种资产的周转率，如存货周转率、应收账款周转率、流动资产周转率和总资产周转率等，以及相对应的周转周期。</p></blockquote><h4><span id="一家公司的短期偿债能力怎么样">一家公司的短期偿债能力怎么样？</span></h4><blockquote><p>__偿债能力（Solvency）__：企业偿还到期债务的承受能力或保证程度，包括偿还短期债务和长期债务的能力。</p></blockquote><blockquote><p>用流动资产除以流动负债便获得了流动比率，这个比值越高，说明企业的短期偿债能力越强。__流动比率（Current Ratio）__：企业流动资产与流动负债的比率，反映企业短期偿债能力。</p></blockquote><blockquote><p>用流动资产减去存货的差除以流动负债，就得到了速动比率，并用它来衡量企业的短期偿债能力。__速动比率（Quick Ratio/Acid-test Ratio）__：速动资产对流动负债的比率。它是衡量企业流动资产中可以立即变现用于偿还流动负债的能力。速动资产中一般不包括流动资产中的存货、一年内到期的非流动资产及其他流动资产。</p></blockquote><blockquote><p>因此，流动资产实际上扮演了两个角色：一个角色是为企业偿还流动负债作准备，另一个角色是为企业的日常运营提供流动资金。当一家公司的流动比率为1，那么它的营运资金一定是不足的。</p></blockquote><h4><span id="企业的长期偿债能力是什么">企业的长期偿债能力是什么？</span></h4><blockquote><p>__息税前收益（Earnings before Interest and Tax）__：扣除利息、所得税之前的利润，英文简称EBIT。</p></blockquote><blockquote><p>__利息收入倍数（Times Interest Earned/Interest Protection Multiples）__：也称利息保障倍数，是指企业息税前利润与利息费用之比；又称已获利息倍数，用以衡量偿付借款利息的能力，它是衡量企业支付负债利息能力的指标。</p></blockquote><blockquote><p>什么是资产负债率？就是用总负债除以总资产。说它粗糙，是因为它涉及包含长期负债和短期负债在内的所有负债，用它来衡量长期负债显然“专业性”不足；说它靠谱，是因为它意味着借钱越多越无法偿还，从这一点看来，倒是直观得不得了。</p></blockquote><blockquote><p>__资产负债率（Liability/Asset Ratio）__：又称财务杠杆（Financial Leverage），是企业负债总额占企业资产总额的百分比。这个指标反映了在企业的全部资产中由债权人提供的资产所占比重的大小，反映了债权人向企业提供信贷资金的风险程度，也反映了企业举债经营的能力。</p></blockquote><blockquote><p>附：财务分析方法汇总一、 同型分析资产负债表的同型分析为资产负债表的每个项目除以总资产，利润表的同型分析为利润表的每个项目除以营业收入。二、 比率分析1.盈利能力[插图]净利率=净利润/营业收入[插图]</p></blockquote><blockquote><p>.偿债能力[插图]（通常用财务费用代替利息费用）[插图]4.投资回报（本书中都采用期末总资产或期末股东权益计算）[插图]</p></blockquote><h4><span id="影响财务数据的因素有哪些">影响财务数据的因素有哪些？</span></h4><blockquote><p>企业决策和企业经济活动之所以千差万别，至少有三方面原因：首先是外部环境存在差异；其次，企业的战略定位也有很大差别；最后，战略的执行能力也会影响企业的现状及未来的发展。</p></blockquote><h4><span id="行业大环境对企业做了些什么">行业大环境对企业做了些什么？</span></h4><blockquote><p>__五力图（Five Forces Model）__：即五力分析模型，是迈克尔·波特（Michael Porter）于20世纪80年代初提出，对企业战略制定产生全球性的深远影响；用于竞争战略的分析，可以有效地分析客户的竞争环境。五力分别是：供应商的议价能力、购买者的议价能力、潜在竞争者进入的能力、替代品的替代能力、行业内竞争者现在的竞争能力。五种力量的不同组合变化，最终会影响行业盈利能力的变化。[插图]图2 五力图</p></blockquote><h4><span id="行业差异如何影响造纸企业和彩电生产企业的财务数据">行业差异如何影响造纸企业和彩电生产企业的财务数据？</span></h4><blockquote><p>应付账款的情况又怎么样呢？说起来，应付账款可是企业最喜欢的东西了。因为企业可以免费占用别人的资金，不需要付利息。在同一个行业里，规模大的公司比规模小的公司更有话语权，也就更能欠别人的钱</p></blockquote><h4><span id="战略定位和执行如何影响企业的财务数据">战略定位和执行如何影响企业的财务数据？</span></h4><blockquote><p>这样一来，成本领先战略的特点就呼之欲出了，它的财务表现就是低毛利而高周转。因为低毛利，所以企业的效益受损，但高周转率又迅速弥补了低效益造成的损失。因此，成本领先战略是一种主动牺牲效益来换取效率的战略，是一种效率制胜的战略。__成本领先战略（Overall Cost Leadership）__：企业通过降低自己的生产和经营成本，以低于竞争对手的产品价格，获得市场占有率。</p></blockquote><blockquote><p>__差异化战略（Differentiation/Differentiation Strategy）__：为使企业产品、服务、企业形象等与竞争对手有明显的区别，以获得竞争优势而采取的战略。这种战略的重点是创造被全行业和顾客都视为独特的产品和服务，是使企业获得高于同行业平均水平利润的一种有效的竞争战略。</p></blockquote><blockquote><p>__规模经济（Economies of Scale）__：大规模生产导致的经济效益的简称，具体是指在一定的产量范围内，随着产量的增加，平均成本不断降低的事实。规模经济是由于一定的产量范围内，由于固定成本变化不大，那么新增的产品就可以分担更多的固定成本，从而使总成本下降。</p></blockquote><h4><span id="好公司是什么样的">好公司是什么样的？</span></h4><blockquote><p>税后营业净利润和净利润究竟相差多少？净利润是扣除了所得税的，同时也扣除了应该付给银行的利息，如果在计算净利润的过程中不扣除利息，但扣除所得税，就得到了税后营业净利润。很显然，这个税后营业净利润既包括股东获得的收益——净利润，也包括债权人获得的收益——利息</p></blockquote><blockquote><p>__投资资本回报率（Return on Invested Capital）__：投出和/或使用资金与相关回报（回报通常表现为获取的利息和/或分得利润）之比例，用于衡量投出资金的使用效果。</p></blockquote><h4><span id="衡量企业投资资本回报率的及格线是什么">衡量企业投资资本回报率的及格线是什么？</span></h4><p><strong>和工程经济学里内部收益率概念类似～内部收益率：是指方案计算期内可以使净现金流量的净现值等于零的贴现率。也就是投资收益必须大于内部收益率，才有投资价值…</strong></p><blockquote><p>__超额收益率（Excess Return）__：超过正常（预期）收益率的收益率，它等于投资资本回报率减去投资资本成本。</p></blockquote><blockquote><p>__经济利润（Economic Profit）__：有时也被称为经济增加值（Economic Value Added），具体是指从税后营业净利润中扣除包括股权和债务的全部投入资本成本后的所得。其核心是资本投入是有成本的，企业的盈利只有高于其资本成本（包括股权成本和债务成本）时才会为股东创造价值。经济利润是一种全面评价企业经营者有效使用资本和为股东创造价值的能力，是体现企业最终经营目标的经营业绩考核工具，也是企业价值管理体系的基础和核心。<br>  __资本成本（Cost of Capital）__：企业为筹集和使用资金而付出的代价。从广义讲，企业筹集和使用任何资金，不论短期的还是长期的，都要付出代价。狭义的资本成本仅指筹集和使用长期资金（包括自有资本和借入长期资金）的成本。由于长期资金也被称为资本，所以长期资金成本也称为资本成本。</p></blockquote><h4><span id="投资资本成本怎么算">投资资本成本怎么算？</span></h4><p><strong>前段时间学工程经济学正好看到：机会成本是指由于资源的有限性，考虑了某种用途，就失去了其他被使用而创造价值的机会。在所有这些其他可能被利用的机会中，把能获取最大价值作为项目方案使用这种资源的成本，称为机会成本。</strong></p><blockquote><p>机会成本</p></blockquote><p><strong>还真是个概念，=_=</strong></p><blockquote><p>__用脚投票（Voting by Foot）__：资本、人才、技术流向能够提供更加优越的公共服务的行政区域。在市场经济条件下，随着政策壁垒的消失，用脚投票挑选的是那些能够满足自身需求的环境。</p></blockquote><blockquote><p>比如说，一家公司有40%的投资资本来自债权人，60%的投资资本来自股东，债权人的贷款利率为7%，而企业所处行业的平均盈利水平是12%，那么，就可以计算出这家企业的投资资本成本为40%×7%+60%×12%，这个所得的结果就是“加权平均资本成本”。__加权平均资本成本（Weighted Average Cost of Capital）__：英文缩写为WACC，具体是指以企业获得的各种资本在企业全部资本中所占的比重为权数，对各种资金的资本成本加权平均计算出来的资本总成本。加权平均资本成本可用来确定具有平均风险投资项目所要求的收益率。</p></blockquote><blockquote><p>A公司比B公司多付了20元利息，而它的利润却只比B公司少15元，原因就在于它少缴纳了5元所得税。因此，虽然A公司向银行付了20元利息，但它实际承担的成本只有15元，其余5元成本由政府承担。</p></blockquote><blockquote><p><strong>利息越高，所得税越少，这被称为“利息的税盾作用”</strong></p></blockquote><p><strong>厉害了！讲的太好了，之前还有点不懂～</strong></p><blockquote><p>和税率相等的部分由政府承担，即20元利息的25%，是为5元；而剩余的部分由企业承担，当为20元利息的75%，是为15元。因此事实上，由企业承担的利息成本应该是7%×（1-所得税税率），答案为5.25%。因此，这家公司的投资资本成本，确切地说是加权平均资本成本应当为：40%×7%×（1-所得税税率）+60%×12%。</p></blockquote><h4><span id="什么是赚钱">什么是赚钱？</span></h4><blockquote><p>而在计算经济利润的时候，我们是用投资资本回报率减去投资资本成本，这相当于把债权人的资金成本和股东的资金成本都扣除了。</p></blockquote><blockquote><p>现在我们知道了，一个好的企业最起码是一个赚钱的企业。什么是赚钱？不是有收入，不是有利润，不是有增长率，甚至不是有利润率。从短期来说，赚钱是有正的经济利润；从长期来说，赚钱是为股东创造价值。</p></blockquote><blockquote><p>[插图]2.投资资本=有息负债+股东权益[插图]注：通常，债务资本成本为贷款利率，权益资本成本可以用行业平均盈利水平衡量。4.经济利润=（投资资本回报率-加权平均资本成本）×投资资本</p></blockquote><h4><span id="企业靠什么赚钱">企业靠什么赚钱？</span></h4><blockquote><p>因此，想成为一个好的企业，首先要选择一个适合自己的战略，然后有效地执行它。只有这样，才能提高企业的总资产报酬率，创造更多的价值。评价一个企业是否是好企业，最终的落脚点就在总资产报酬率</p></blockquote><h4><span id="股东提高收益得依靠什么">股东提高收益得依靠什么？</span></h4><blockquote><p>__权益乘数（Equity Multiplier）__：又被称为股本乘数，是指资产总额相当于股东权益的倍数。表示企业的负债程度，权益乘数越大，企业负债程度越高。</p></blockquote><blockquote><p>附：权益乘数＝资产总额÷股东权益总额即=1÷（1-资产负债率）。</p></blockquote><h4><span id="这是一家怎样的企业">这是一家怎样的企业？</span></h4><blockquote><p>要判断一家企业的经营情况如何，我们最需要关注的是它的投资回报，也就是总资产报酬率。投资回报由两方面因素决定，一是企业的效益，二是企业的效率：</p></blockquote><h4><span id="a公司怎样在费用上落了下风">A公司怎样在费用上落了下风？</span></h4><blockquote><p>__债务融资（Debt Financing）__：是指通过银行或非银行金融机构贷款或发行债券等方式融入资金。债务融资可进一步细分为直接债务融资和间接债务融资两种模式。直接债务融资如发行债券，间接债务融资如银行贷款。</p></blockquote><h4><span id="a公司的周转率为什么会被秒杀">A公司的周转率为什么会被“秒杀”？</span></h4><blockquote><p>附：A公司效益、效率落后原因的总结1.作为一个大规模企业，它并没有享受到规模经济性企业应该具有的成本优势，这源于它所采取的多产品格局，但每一种产品并不具有明显的大规模。2.A公司在过去几年大力建设原材料生产基地，不仅自己种树，还收购了具备纸浆生产能力的企业。但种树是一件慢工出细活的工作，它并没有在节约A公司成本方面发挥作用；作为竞争对手的B公司，虽然没有过多举措，但它用草浆生产对原材料要求不高的新闻纸，从而获得成本上的优势。3.在造纸行业这样一个资金密集型行业内，A公司的规模和产能对它的融资需求提出了很高要求，使该企业不得不承担更高的财务费用。4.原材料、生产以及销售地域不匹配，造成大量运费。5.过去几年快速的兼收并购使A公司的管理面临挑战，能否顺利整合这些并购来的企业是悬挂在A公司头上的达摩克利斯之剑。6.A公司的固定资产中有诸多在建项目，这些在建项目不能在现阶段为公司带来收益，这是它周转率低的一个重要原因。7.A公司储备了大量原材料，它们也不能带来收入，反而拖了周转率的后腿。</p></blockquote><h4><span id="健康企业的现金流有哪些特征">健康企业的现金流有哪些特征？</span></h4><blockquote><p>__企业的生命周期（The Life Cycle of Enterprise）__：一般包括初创阶段、成长阶段、成熟阶段和衰退阶段。也有更细的划分方法。通常在初创阶段，企业利润和现金流都较差；成熟阶段现金流丰厚，但是由于行业竞争加剧，盈利能力一般。</p></blockquote><h4><span id="经营活动现金流为负的企业怎么样">经营活动现金流为负的企业怎么样？</span></h4><blockquote><p>投资活动的现金流入有两种类型：第一种是处置资产，这其中包括处置固定资产、无形资产和对外投资；第二种则是投资收益。很显然，如果这个企业的现金流入类型属于前者，它就并没有找到一个能给它带来持续现金流入的项目，而只是处置了那些盈利状况不好的资产，这类企业未来的风险是相当大的。</p></blockquote><h4><span id="三张报表之间有何牵连">三张报表之间有何牵连？</span></h4><blockquote><p>资产负债表和利润表告诉我们公司的运营情况，现金流量表告诉我们公司的风险状况，通俗点概括：如果资产负债表和利润表说这个公司好，说明它赚钱；现金流量表说这个公司好，说明它有钱。既赚钱又有钱的企业当然是一个好企业，一个既不赚钱又没有钱的企业一定糟糕透了。</p></blockquote><blockquote><p>净利润和现金净流量之间的差额，永远等于资产负债表上除现金之外其他资产和负债的变化。</p></blockquote><h4><span id="什么样的公司更应该关注现金流量">什么样的公司更应该关注现金流量？</span></h4><blockquote><p>比如说，卖出产品之后，企业的利润表就会产生变化，但如果没收回钱，企业就没有经营活动的现金流入。所以这时候，企业账上的利润可能不错，但现金流并不好。</p></blockquote><h4><span id="利润和现金流究竟哪个更重要">利润和现金流究竟哪个更重要？</span></h4><blockquote><p>说来说去，两个企业其实联合起来告诉了我们一个统一的结论：当一个企业遭遇巨大风险的时候，关注风险是第一位的，现金流对它来说更重要；当企业经营活动的风险在相对可控的范围内时，利润就显得更为重要。</p></blockquote><h4><span id="在企业内部决策中该如何应用财务数据">在企业内部决策中该如何应用财务数据？</span></h4><blockquote><p>财务分析可以在很大程度上帮助企业作出决策。对A公司而言，它就能通过这种分析找出自己的软肋，从而找到明确提升企业价值的方式。一个企业全面了解自身的状况，会有助于它未来更好地规划自己的发展战略。</p></blockquote><h4><span id="在企业投资决策中如何应用财务数据">在企业投资决策中如何应用财务数据？</span></h4><blockquote><p>__资金的时间价值（Time Value of Money）__：随着时间的推移而产生的资金的价值增值，这个增值源于投资收益。因此，不同时间点的资金不能简单相加，当前的资金数额+投资收益=未来的资金数额，这里的当前资金数额与未来资金数额不相等，但是价值相同。</p></blockquote><blockquote><p>__贴现（Discount）__：将未来的资金折算为当前资金数额的过程。未来资金数额÷（1+贴现率）=当前资金数额，这里的贴现率是投资收益率，在投资决策中一般为企业的加权平均资本成本。</p></blockquote><blockquote><p>__净现值（Net Present Value，NPV）__：投资项目未来收益贴现之后的总和减去投资成本之后的差额。一般认为，只有净现值大于0的项目才可行。</p></blockquote><h4><span id="点评">点评</span></h4><p>★★★★★</p><p><strong>这本书讲的真的很不错，通俗易懂，很多枯燥的经济学理论、概念都解释的很棒，对这方面感兴趣的朋友可以看看。有些概念我在其他书上看过，当时还有点不理解，但是在这里再看到的时候，就都明白了。</strong></p>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;在会计眼中，企业都在忙些什么？&quot;&gt;&lt;a href=&quot;#在会计眼中，企业都在忙些什么？&quot; class=&quot;headerlink&quot; title=&quot;在会计眼中，企业都在忙些什么？&quot;&gt;&lt;/a&gt;在会计眼中，企业都在忙些什么？&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;日子就这样一天天地过，企业就这样一天天地经营、投资、融资。&lt;/p&gt;
&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="读书笔记" scheme="http://landerqi.com/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>学诚法师-好好听话</title>
    <link href="http://landerqi.com/2018/09/04/%E5%AD%A6%E8%AF%9A%E6%B3%95%E5%B8%88-%E5%A5%BD%E5%A5%BD%E5%90%AC%E8%AF%9D/"/>
    <id>http://landerqi.com/2018/09/04/学诚法师-好好听话/</id>
    <published>2018-09-04T02:28:48.000Z</published>
    <updated>2019-07-02T06:28:51.126Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="耳根最利谛听谛听善思念之">耳根最利：“谛听，谛听，善思念之”</span></h3><blockquote><p>听闻，本身叫作闻慧，思叫思慧，不断修行，最后才能开智慧。所以，佛门里说“听闻随转修心要，少力即脱生死城”。</p></blockquote><span id="more"></span><blockquote><p>曾经有位古希腊哲学家，晚年的时候声望很高，拥有上千名学生。一天，这位两鬓花白的老者蹒跚着走进课堂，手中捧着一摞厚厚的纸张。他对学生说：“这堂课你们不要忙着记笔记，凡是认真听讲的人，课后我都会发一份笔记。一定要认真听讲，这堂课很有价值！”学生们听到这番话，立刻放下手中的笔，专心听讲。但没过多久就有人自作聪明——反正课后老师要发笔记，又何必浪费时间去听讲呢？于是开起了小差。临近下课时，这些学生觉得并没听到什么至理名言，不禁怀疑起来：这不过是一堂普通的课，老师为什么说它很有价值呢？课讲完了，哲学家将那摞纸一一发给每位学生。领到纸张后，学生们都惊叫起来：“怎么是几张白纸呀？! ”哲学家笑着说：“是的，我的确说过要发笔记，但我还说过请大家一定要认真听讲。如果你们刚才认真听讲了，那么请将在课堂上所听到的内容全部写在纸上，这不就等于我送你们笔记了吗？至于那些没有认真听讲的人，我并没有答应要送他们笔记，所以只能送白纸！”学生们无言以对。有人懊悔刚才听讲心不在焉，面对白纸不知该写什么；也有人快速地将所记住的内容写在白纸上。后来，只有一位学生几乎一字不落地写下了老师所讲的全部内容，他也是哲学家最得意的学生。哲学家满意地把这位学生的笔记贴在墙上，大声说：“现在，大家还怀疑这堂课的价值吗？”</p></blockquote><blockquote><p>仔细倾听人们的谈话，他们自然会教你如何好好生活有这样一则小故事。有一天，猫妈妈把小猫叫来，说：“你已经长大了，三天之后就不能再吃妈妈的奶了，要自己去找东西吃。”小猫惶惑地问妈妈：“妈妈，那我该吃什么东西呢？”猫妈妈说：“你要吃什么食物，妈妈一时也说不清楚，就用我们祖先留下的方法吧！这几天夜里，你躲在人们的屋顶上、梁柱间、陶罐边，仔细倾听人们的谈话，他们自然会教你的！”第一天晚上，小猫躲在梁柱间，听到一个大人对孩子说：“小宝，把鱼和牛奶放在冰箱里，小猫最爱吃鱼和牛奶了。”第二天晚上，小猫躲在陶罐边，听见一个女人对男人说：“老公，把香肠和腊肉挂在梁上，小鸡关好，别让小猫偷吃了。”第三天晚上，小猫躲在屋顶上，从窗户听到一个妇人向自己的孩子叨念：“奶酪、肉松、鱼干吃剩了也不收好，小猫鼻子很灵，明天你就没得吃了。”就这样，小猫每天都很开心，它回家告诉妈妈：“妈妈，果然像您说的一样，只要我仔细倾听，人们每天都会教我该吃什么。”这个故事虽然很简单，但却能给予我们很深刻的启发：在生活、学习和工作中，很多时候需要我们用心去倾听，用心去学习。倾听不仅是一种态度，也是一种技能。做一只善于倾听的小花猫吧！</p></blockquote><blockquote><p>听话的艺术，一是听话不要听一半；二是不要把自己的意思投射到别人所说的话上，就是不要先入为主。否则，就会失去获得真相的机会。</p></blockquote><p><strong>同理心</strong></p><blockquote><p>放下自己，完全站在对方的角度，才有能力认真倾听别人的心声，去理解、去接纳，即使只有片刻。只要长时间地去练习，我们就会越来越接近对方，才能真正地帮到对方。</p></blockquote><blockquote><p>究其根本，听别人讲话，实际上是自己的心在与人交流。我们对别人的排斥、抵触，别人立刻就能感觉到。本来花时间听别人讲话是为了沟通交流，结善缘，结果不听还好，一听反而结了怨。</p></blockquote><blockquote><p>有经验的禅师会适机批评自己的弟子，挖苦他、责骂他、讥讽他，让他下不来台，营造种种境界，看他怎么办。而够量的弟子就能在这些逆耳的语言当中获得不一样的人生体悟。</p></blockquote><blockquote><p>烦恼中有一种叫“嗔心”的烦恼，俗称仇恨，就是在人与人相处的过程中，一旦听到不喜欢的话，内心就会有一股“劲”出来，佛门里也会比喻为“热恼”。</p></blockquote><blockquote><p>真的忍辱，不是在忍别人，是在与自己斗。他人的语言是空气罢了，内心的“贼”才是伤害自己的元凶。</p></blockquote><blockquote><p>批评和指责是我们一生都要面对的境界，在批评中得体地用心，是一个人成长和进步的基本素质，也是事业成功和生活幸福的基本条件。</p></blockquote><blockquote><p>一般情况下，每个人在学习中，比较会顾忌自己的面子，不情愿承认自己的短板，愿意让别人看到自己的长处。这样一来，就不容易进步了。</p></blockquote><blockquote><p>佛法告诉我们，对他人好，一定要选择对方能够接受的方式，否则就容易把自己的想法强加于人，反而对他人造成压力。这种“掏心掏肺”的好，其实是我执的另一种体现，还不够“好”，不是真好。改善的方法是突破“以自我为中心”的思维习惯，多用心去关注他人的处境与心情，放下自己的见解与论断，尝试去倾听、理解他人。这样慢慢就能从烦恼的紧紧束缚中解脱出来。</p></blockquote><blockquote><p>这种心理模式在佛法中有很精确的定义，就是“我执”——凡是“我”认为对的事情，大家都要这样认为；凡是“我”决定的事情，别人就不能更改。就是凡事都要顺着“我”的意思来，否则就不行。一个家庭中，每个人都有“我执”，程度轻重不同，角度不同。有的在这个地方很执着，有的在那个地方很执着；有的是对大事执着，有的是对小事执着。换句话说，就是“以自我为中心”的思维模式。</p></blockquote><blockquote><p>只是，懂得道理不难，难的是放下自己的想法，去接受、理解、倾听、尊重别人，那一刻需要很大的勇气和力量来突破。只要有改变，一切就都还有机会。</p></blockquote><h3><span id="第二章-是非以不辩为解脱">第二章 “是非以不辩为解脱”</span></h3><blockquote><blockquote><p>要有放得下的洒脱，要有拿得起的担当，凡事要“认真而不当真”</p></blockquote></blockquote><h3><span id="别人口中的你好也罢坏也罢都不是真正的你">别人口中的你，好也罢，坏也罢，都不是真正的你</span></h3><blockquote><p>想一想看，外人无论怎么说，贬损的都是他内心认为的那个你，从来也不可能伤害到真正的你，因为真正的你是变化的。</p></blockquote><blockquote><p>要懂得：别人的评价好听还是难听都不重要，重要的是你自己怎么对待。处理得好，好听的话是鼓励，难听的话是激励；处理不好，好听的话是奉承，难听的话是伤害。</p></blockquote><blockquote><p>未来也不是他人口里的，而是自己营造的。要相信自己，相信业果，工作与生活中，多看好样子，远离坏样子，诸恶莫作，众善奉行。</p></blockquote><blockquote><p>当你不再畏惧外在的目光，外在就会为你让路</p></blockquote><blockquote><p>佛法告诉我们，世间没有任何一个局面是永恒的，任何事都有因有缘有果，一切都在改变中。所以，我们一定要有向前看的勇气，因为任何一次自我更新，都要先经历挫伤和打碎的痛苦。就如做手术一样，开刀是痛苦的，但取出毒瘤就是新的开始。</p></blockquote><blockquote><p>缺点再多的说谎者也有优点，要能够找到他的优点，给予肯定，慢慢找到适当的机会鼓励对方改变。</p></blockquote><blockquote><p>佛法教我们这样作意：学会让那些骂声随风而逝，不要录下来反复重播，这个“录音机”就是自己的心。</p></blockquote><blockquote><p>是非以不辩为解脱，凡事要“认真而不当真”</p></blockquote><blockquote><p>所以，既要有本事把别人的坏话“不当真”，又要有能力去做出实实在在帮助他人的事情来，这才是足够好的。有句话说：一等人有本事没脾气，二等人有本事有脾气，三等人没本事没脾气，四等人没本事有脾气。</p></blockquote><blockquote><p>同时，凡事要“认真而不当真”，二者少了哪一个都不行。当真，就容易变成执着；不认真，就容易流于放逸。对人对事要有放得下的洒脱，也要有拿得起的担当。如果仅仅是玩笑人生，那生活就会变成一个玩笑。</p></blockquote><blockquote><p>“不公正的待遇”，是在自己的判断和比较之中成立的——自己认为自己应该得到何种对待，然而却没有得到，别人却得到了。这是站在自己的角度去看待问题而得出的结论。但有时候，我们自己看待问题是相当片面的，所了解到的信息也不完整，并常常高估自己的付出，最后与现实相撞，觉得失衡、愤懑。</p></blockquote><blockquote><p>现实生活中，尤其是职场上，当觉得自己遭受了不公平的待遇时，不要第一时间怀疑主事者是出于私心而感到烦恼，而应当冷静下来，换位思考，好好反省自己的行为是不是有可改进之处，别人有什么值得学习之处，否则很容易带着烦恼去看待他人，造成错误的判断。</p></blockquote><blockquote><p>有一次，丰子恺寄一卷宣纸给弘一法师，请他写佛号。宣纸多了些，弘一法师就写信问丰子恺：多余的宣纸如何处置？这就说明弘一大师深深懂得尊重别人，善于听取别人的意见，什么事情都不会自以为是，自作主张。</p></blockquote><blockquote><p>为什么我们很多人不能成事？就是因为有障碍——人与人的障碍，事与事的障碍。所以我们要去体会，才能知道什么是有违，什么是无违。</p></blockquote><blockquote><p>职场和社会有这样一个共识，你的成功取决于和对方谈话时让对方愉悦的程度</p></blockquote><p><strong>有道理</strong></p><blockquote><p>人与人之间的沟通，不是说服对方，而是理解对方；不是告诉对方，我多么有能力，而是告诉对方，我愿意接受你的想法，体恤你的感受。<br>世间常有“话不投机半句多”的说法，这是什么原因呢？佛法告诉我们，首先我们会产生种种的认识和想法，这些想法只是想法而已，是会变化的，这就是无常。今天这么认为，明天可能就那么认为。今年这么想，明年可能就会那样想，时时刻刻都在变化。</p></blockquote><blockquote><p>人与人之间的沟通，不是说服对方，而是理解对方；不是告诉对方，我多么有能力，而是告诉对方，我愿意接受你的想法，体恤你的感受。世间常有“话不投机半句多”的说法，这是什么原因呢？佛法告诉我们，首先我们会产生种种的认识和想法，这些想法只是想法而已，是会变化的，这就是无常。今天这么认为，明天可能就那么认为。今年这么想，明年可能就会那样想，时时刻刻都在变化。</p></blockquote><h3><span id="一个人有没有智慧第一就看你会不会听话">一个人有没有智慧，第一就看你会不会听话</span></h3><blockquote><p>在佛经里，说人有六根——眼、耳、鼻、舌、身、意，其中，耳根最利。利是锋利、最厉害的意思。在《楞严经》里就有《观世音菩萨耳根圆通章》，讲的是由耳根入道，一门深入。《楞严经》里还讲，“从闻思修入三摩地”。要想入三摩地，第一个还是闻——听闻。</p></blockquote><blockquote><p>在修行中，“好好说话”与“好好听话”是有区别的，一个是讲说，一个是听闻，即内修外弘。“好好听话”是内修，是修自己；“好好说话”实际上就是要度众生，是外弘。</p></blockquote><blockquote><p>一句话：好好说话是启发别人，说别人需要的话；好好听话是启发自己，是修自己。</p></blockquote><blockquote><p>所谓“起心动念皆为错”。《楞严经》里用八个字讲得更透彻——“狂心顿歇，歇即菩提”。</p></blockquote><blockquote><p>在做一件事的过程中，如何区分自己是出于贪心还是欢喜心呢？其一，我们在做一件事的时候，如果以利己的贪心为动力，就一定会痛苦；以利他的欢喜心为动力，导向就是快乐。换句话说，要衡量自己是否有贪心，就要看看做事的时候是否有痛苦。其二，观察做事的起心动念是否有恶。如果起心动念不对，是贪心在作祟，你就会患得患失，痛苦不堪，以致在克服困难时受到极大的阻碍。怎么克服贪心呢？就要按照佛教的次第来修行：布施，持戒，忍辱，精进，禅定，智慧；按照佛教的理论来修自己的心。</p></blockquote><blockquote><p>傲慢就是看不起别人。身体好的看不起身体差的，漂亮的看不起难看的，健康的看不起不健康的，有地位的看不起没地位的……都是病态。做人，一定不要傲慢，平平常常的，大家都和睦相处，多好！</p></blockquote><h3><span id="不该知道的你就先不要知道">不该知道的，你就先不要知道</span></h3><blockquote><p>因为佛门有解门和悟门：开了解门，往往就可能关上了悟门；开着悟门，就不要打开解门。说白了，就是不该知道的，你就先不要知道。真听话的，师父的办法就会比较多；不听话的，师父就不好办。自己懂得太多，最后谁的话也听不进去，就不好悟了。</p></blockquote><blockquote><p>在《菩提道次第广论》这部论典里，有一个很著名的比喻，把错误的闻法状态分为三类。第一类，倒扣着的碗。就是说，碗倒扣在桌子上，绝对不可能装进水。比喻我们不想听闻，或者根本就没有能力听闻。在现实生活中，如果仔细观察，会发现人与人之间的差距很大。有的人听一遍就能记住；有的人不管怎么讲，或者没听见，或者没听懂，或者走神了，总之，就是不知道在讲什么。这样的人一般都属于有业障——听闻的能力有障碍。第二类，碗底有个洞。什么意思呢？水是倒进碗里了，但是会漏掉，倒多少漏多少。比喻我们在听闻善知识言教的时候，虽然听了，但是不思考，不重视，听完就忘记了。所以，我们听到了善知识的言教还不算，还应该反复地思维，如同在木头上刻印迹，反复刻，这样才能在心里留下很深的刻痕。如果不思维，就如同水上的涟漪，很快就消失了。第三类，脏碗。一个碗里很脏，有污垢，甚至是有毒，无论什么水倒进去，都会变成脏水或者毒水。比喻我们在听闻善知识言教的时候，内心已经有了一个想法、观念，无论听进去什么，都会被这些先入为主的观念解读和染污，得出的结论当然和听闻的善知识的言教本意大相径庭，甚至南辕北辙。</p></blockquote><blockquote><p>一位居士，大学毕业之后开始学佛，父母很不情愿，甚至很反对，常常为此有情绪。但是，经过几年的学习之后，发生了一件事情，彻底改变了父母对孩子学习佛法的态度。有一天，这位年轻居士开车带父母去医院看病，在路上，母亲拿起一颗糖，刚吃了一半，父亲就急了，嚷道：“你怎么回事，不知道自己有糖尿病吗？这么不懂得节制，那还看什么病呢？”母亲立刻反唇相讥：“用你说，我不就吃块糖，犯得上你这么说我吗？”车内的气氛立刻紧张起来，大家非常不愉快。按照以往的情况，再来两句，就会爆发更激烈的争吵。这时孩子跟母亲说：“妈妈，我爸不让你吃糖，他不是说你，他只是不太会表达而已。他是想说，他很需要你，很爱你，希望你健康，很害怕失去你，所以就会着急，一着急说话就会不好听。你不要听他的那个不好听，要听他对你的爱。”母亲沉默了。孩子又跟父亲说：“爸，我妈已经病了，她更需要宽慰。你那样跟她说话，也没有错，只是妈妈生病期间，身体不好，心情也不好，所以就会不接受。她也不是故意要跟你吵架，故意跟你对着来，她就是习惯了。你多理解她。”父亲也沉默了。车里的气氛一下就缓和下来，然后父亲跟母亲说：“好吧，是我不好，不该那样跟你说话，是我太着急了，以后我会改一改我的习惯。”母亲则跟父亲说：“我确实不该吃糖，本来就生病，让家里人着急，确实不好。以后我多注意。”</p></blockquote><h3><span id="人们爱上的往往是被爱的感觉">人们爱上的，往往是“被爱”的感觉</span></h3><blockquote><p>__问__：法师，这困扰世间的爱情该如何理解呢？<br><br>__学诚法师__：很多人所谓的“爱情”其实是一种交换：因为我对你好，所以希望你也对我好；人们爱上的，往往是“被爱”的感觉，是对自我的满足。所以，当这种“交换”不平等时，就产生了痛苦。真正的爱，是没有执着、没有要求、没有期盼的。</p></blockquote><blockquote><p>1．万事皆无常；2．命运掌握在自己手里；3．为还没有发生的事情纠结，是妄想。</p></blockquote><h3><span id="第六章-如何与父母好好相处">第六章 如何与父母好好相处</span></h3><blockquote><p>下雨了，撑伞就好，不要去记恨老天爷。</p></blockquote><h3><span id="为什么孝是色难">为什么孝是“色难”</span></h3><blockquote><p>浮躁、暴躁，是因为自己一直在排斥眼前的因缘，没有安住当下。内心一直在串习“我真命苦”“为什么要我做这些事情”等负面情绪，只会越来越深地陷入烦恼的泥潭。要转一种心态去面对，接纳现状，全心成长。污泥能令莲花更光华，磨砺能使钻石更闪耀。</p></blockquote><h3><span id="第七章-如何跟孩子好好相处">第七章 如何跟孩子好好相处</span></h3><blockquote><p>去理解，去倾听，与任何人沟通的前提，都是心中不要有成见。</p></blockquote><h3><span id="第八章-没有人会白白受苦">第八章 没有人会白白受苦</span></h3><blockquote><p>沉浸在自己的烦恼中，很难完全看清事实的真相，向上走的每一步中受的苦都是资粮。</p></blockquote><h3><span id="爱别离-求不得-怨憎会人生总是会经历这些苦">爱别离、求不得、怨憎会，人生总是会经历这些苦</span></h3><blockquote><p>当发现命运不如意，就要仔细反省自己性格中的缺点、行为上的过失，把这些改过来，命运就能改变。</p></blockquote><blockquote><p>学习、做事，我们都不需要取悦别人，而是为自己负责。诸法无自性，成功是因为有成功的因缘，失败是因为有失败的因缘，只要我们去改变因缘，就能改变结果。相信自己会改变、会成长，而不是一直怀着负面的心退缩。</p></blockquote><blockquote><p>慢心重的人，喜欢观察别人的缺点，评论别人的过失；不容易与别人合作，处处想表现自己，得到别人的赞扬；不能采纳别人的意见，不能容忍比自己强的人。</p></blockquote><blockquote><p>存好心、说好话、做好事。想着更多的人，帮助更多的人。豁达、乐观、宽厚，不计较，不怕吃亏。不说人是非，不讥讽嘲笑，不怨天尤人，不轻浮卖弄。</p></blockquote><h3><span id="人直好吗">人“直”好吗</span></h3><blockquote><p>不要因为内心的反感而失去了成长的机会，抛开情绪，心平气和地听听他的话是否有道理。若他的确指出了自己所看不到的缺点，正好借此改正；若他的话不属实，正好忍辱消业。</p></blockquote><blockquote><p>自己快乐、痛苦只有自己真正知道，不是别人说我们好才快乐，别人说一句不好就痛苦。人过得好不好，在于是否认可自己生命的品质，是否具备有价值、有意义的生命信念。</p></blockquote><blockquote><p>__问__：师父，我周围的同事每天都在为了评职称而拼搏，我自己对职称没兴趣，倒像很不上进似的。我只想好好提高教学水平，将来有因缘就去寺里念佛修行，可是为什么心里乱乱的？<br><br> __学诚法师__：有时候，我们对佛法的信心很弱，就会担心自己不去争是不是吃亏了，是不是不上进了；有时候，我们又看不起周围的人，觉得他们争名夺利太庸俗，内心很排斥。这些都不是如理思维，都是烦恼。真正对佛法有信心，内心不会纠结、矛盾；自己不求，也不要看不起求的人。</p></blockquote><blockquote><p>当你被人看不起的时候，是什么心情？己所不欲，勿施于人，当发现自己看轻别人时，要这样换位去想一想。此外，容易看不起别人的人，要刻意去看他人的优点。如果发现自己都想不起身边的人有什么优点，那就说明自己的“慢心病”很重，得治。慢心是一种错觉，既不如实了知自己，也没有如实了知别人，只是内心构建出一个“自己”的形象，与自己幻想的“他人”比较而产生的一种烦恼。这恰恰证明了自己的无知，是自己看不到他人的长处，不代表别人没有超过自己的地方。当发现自己起慢心的时候，好好反观内省，看清念头，辨明妄想。</p></blockquote><blockquote><p>先不要着急辩解，冷静地把他的话都听进去，从中寻找自己的盲区和漏洞，力争改进。他人的指责和批评，不管有没有道理，在我们听来往往都是偏颇的、错误的，这恰恰是因为我们很难发现自己的问题——人不会故意去做自己以为错的事。消解积怨，正是要靠自己放下执着，努力改变。</p></blockquote><blockquote><p>自信不能变成自满，“满”就是到头了，没有什么可以学习的东西了，只有自己最好、最对，别人都不如自己。自信是相信自己有学习、成长的能力，不惧每一次挑战和失败，而非和别人比较而产生的骄傲。</p></blockquote><blockquote><p>如蜂采蜜，只取其蜜。如果真心把自己的成长放在首位，那么听到别人指出自己的问题就会如获至宝，闻过则喜，因为这是真正有价值的，正是自己想要的。而因为别人的态度耿耿于怀，还是在意自己的面子，保护自己的我执罢了，都是自己的妄想和执着。</p></blockquote><blockquote><p>别人怎么能“贬损”到自己呢？他人的话只是一个音节罢了，从说出口的瞬间就消失在空气中了，如果自己没有听到，那么就跟没有发生过一样。自己“不舒服”，是因为顺着别人的概念去理解、接受、想象，把这些语句当作了真实的境界，其实根本不是如此。</p></blockquote><blockquote><p>因为道理是道理，自己是自己。所谓“懂得”的道理，是别人总结出来，自己听懂的，这跟自己思维得到的、在生活中运用的是两回事。听了很多道理，却从未真正纳入心灵，犹如病者空负药囊，却从未吃药一样。</p></blockquote><h3><span id="总是希望别人理解自己就很少将心思放在去理解别人上">总是希望别人理解自己，就很少将心思放在去理解别人上</span></h3><blockquote><p>如果你的意图是想“说服”对方，那就是“极难”的；如果你做好准备去“倾听”对方，才是真正的“沟通”。</p></blockquote><blockquote><p>不要总想别人为什么不理解自己，多去想想自己是否理解别人。</p></blockquote><blockquote><p>“见贤思齐焉，见不贤而内自省也。”</p></blockquote><blockquote><p>心里不要怕累，越觉得累，越怕累，就越累。做完一件事就放下一件事，永远只面对当下一件事。</p></blockquote><blockquote><p>守愚守谦，常居学处。</p></blockquote><blockquote><p>最佳的管理莫过于信仰——让每个人都明白自己的意义所在。</p></blockquote><blockquote><p>“不公平对待”，是在自己的判断和比较之中成立的——自己认为自己应该得到何种对待，然而却没有得到，别人却得到了，这是站在自己的角度去看待问题而得出的结论。但有时候，我们看待问题是相当片面的，所了解到的信息也不完整，并常常高估自己的付出，与现实相撞，就会觉得失衡、愤懑。当觉得自己遭受了不公平对待时，不要第一时间怀疑主事者有私心，而应冷静下来，换位思考，好好反省自己的行为是不是有可改进之处，别人有什么值得学习之处，否则很容易带着烦恼去看待他人，做出错误的判断。</p></blockquote><h3><span id="佛氏门中有求必应吗">佛氏门中，有求必应吗</span></h3><blockquote><p>智慧分为闻慧、思慧、修慧，前者为后者之因。增长智慧，从听闻开始。</p></blockquote><p><strong>Stay hungry, stay foolish</strong></p><blockquote><p>承认自己的无知，才能学到知识。</p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;耳根最利：“谛听，谛听，善思念之”&quot;&gt;&lt;a href=&quot;#耳根最利：“谛听，谛听，善思念之”&quot; class=&quot;headerlink&quot; title=&quot;耳根最利：“谛听，谛听，善思念之”&quot;&gt;&lt;/a&gt;耳根最利：“谛听，谛听，善思念之”&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;听闻，本身叫作闻慧，思叫思慧，不断修行，最后才能开智慧。所以，佛门里说“听闻随转修心要，少力即脱生死城”。&lt;/p&gt;
&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="读书笔记" scheme="http://landerqi.com/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>学诚法师-好好说话</title>
    <link href="http://landerqi.com/2018/08/31/%E5%AD%A6%E8%AF%9A%E6%B3%95%E5%B8%88-%E5%A5%BD%E5%A5%BD%E8%AF%B4%E8%AF%9D/"/>
    <id>http://landerqi.com/2018/08/31/学诚法师-好好说话/</id>
    <published>2018-08-31T14:10:48.000Z</published>
    <updated>2019-07-02T06:28:51.127Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="上篇-说好话积福报">上篇 说好话积福报</span></h3><blockquote><p>智慧是什么呢？智慧就是当别人用戾气对你的时候，首先你要抱有一颗慈悲心，然后去寻找化解的办法。</p></blockquote><blockquote><p>好好地修慈心、悲心、喜心、舍心。这些心念修好以后，我们说出来的话，肯定是出于好心，肯定是对方能接受的好话。</p></blockquote><span id="more"></span><h3><span id="中篇-家家都有一本难念的经">中篇 家家都有一本难念的经</span></h3><blockquote><p>每个人的生命都有顺境和逆境，一般都是顺逆交替的。如果顺境处理不好，就会变成一种逆境；如果逆境处理得好，就会变成一种顺境。就好比在高速公路上开车，路况好时，安全这根弦就容易放松；如果在一个路况很差的地方行驶，注意力反而会很集中。所以，不是路好路坏的问题，而是心态问题。人生也是如此。</p></blockquote><blockquote><p>抓不住的东西不要去抓。当完全明白一切事物都是抓不住的，生命反而真正自由、安全、快乐了——从此不会被任何东西“抓住”，没有了忧虑、恐惧，不再会嫉妒、愤怒、苦恼。没有任何心理障碍，才是一个真正能“提起”、会承担、有力量的人，也是一个真正能“放下”的人。</p></blockquote><blockquote><p>就这样，富翁再也没听到隔壁的笑声了。其实仔细想一想，外在的这些物质，我们真正需要的并不多，都是想要的太多。</p></blockquote><blockquote><p>而故事里，孔子却说：“我相信颜回之仁已经很久了。你虽如此说，我仍不会怀疑他，这里边必定有缘故。”</p></blockquote><blockquote><p>“刚才有灰尘掉进饭里，留在锅里不干净，丢掉又太可惜，我就把它吃了，不可以用来祭奠了。”</p></blockquote><blockquote><p>高调低调，看胸襟；大事小事，看担当；顺境逆境，看把握；是得是舍，看欲望；成败得失，看坚持；淡然释然，看心情；是非曲直，看度量。心小，小事则大；心大，大事则小。大其心，容天下之事；虚其心，赏天下之美；潜其心，究天下之理；定其心，应天下之变。</p></blockquote><blockquote><p>懂得无常，心就不会被外在的境界所束缚，能够看淡得失成败；懂得无常，要好好珍惜生命的时光，勤造善业；懂得无常，要在一切境界中善待他人，温暖自己。</p></blockquote><blockquote><p>一切都是因果。别人今天得到的，是他过去造的善业；你没有得到，是你过去没有造这个业。你今天得到了，也不用得意，那是你过去造的善业，现在感果。</p></blockquote><blockquote><p>__学会赞美~__，<br>其实，赞叹别人是很便宜的，别人需要鼓励了，你赞叹他一下，让他获得利益，这本来就是一种布施。</p></blockquote><blockquote><p>人生不如意事十之八九。佛教注重的不是让我们事事顺利如意，而是让我们通过学习和修行获得克服困难的能力。</p></blockquote><blockquote><p>究其根本，我们的痛苦不是源于外在的人、事、物，而是源于我们内心，外在只是一个缘罢了。</p></blockquote><blockquote><p>一切都会过去，我们要有接受一切事物的勇气。当事情发生时，我们先是觉察到它，面对它，然后平静地接纳它，尽心尽力地处理它，洒脱地放下它。</p></blockquote><h3><span id="第三章-如果你因为错过太阳而哭泣那么你也将错过漫天繁星">第三章 『如果你因为错过太阳而哭泣，那么你也将错过漫天繁星』</span></h3><blockquote><p>『如果你因为错过太阳而哭泣，那么你也将错过漫天繁星』</p></blockquote><blockquote><p>佛教讲“一切唯心造”“心生则种种法生”。意谓心的力量是无穷的，一切的法都是从心而生起的。</p></blockquote><blockquote><p>现实生活当中，很多人比较无明，他们会在人前不自觉地高谈自己的得意之事。在佛门里，这叫自扬己德，是犯戒的事。要知道，这个世界上唯一给你带来痛苦的，就是对自我的仰视和执着，所以，人越是拥有，越要谦虚低调。在佛门看来，低调就是要破我执。</p></blockquote><blockquote><p>阿拉伯有句谚语：“为了玫瑰，也要给刺浇水。”意思是说，在这个竞争激烈的社会，要想出人头地，有所成就，让自己的人生开出美丽之花，就必须忍住一时之气，忍住那些扎在心头的芒刺，将其化为前进的动力，方能博得成功。</p></blockquote><blockquote><p>我们的生命就像高僧手中的那杯茶水一样，转瞬间就和泥土化为一体。光阴如此短暂，生活中一些无聊小事，又哪里值得我们花费时间去生气呢？</p></blockquote><blockquote><p>穷人问佛：“我为何穷？”佛说：“你没有学会给予别人。”穷人：“我一无所有如何给予？”佛说：“一个人一无所有也可以给予别人七种东西：颜施：微笑处事；言施：说赞美安慰的话；心施：敞开心扉对人和蔼；眼施：善意的眼光给予别人；身施：以行动帮助别人；座施：即谦让座位；房施：有容人之心。”</p></blockquote><blockquote><p>对我们来说，“重新开始”最大的障碍，是我们内心的阴影，是我们内心对过去失败印象的反复加深，是我们心头的第二支箭。往往是这第二支箭，让我们丧失了前进的勇气。</p></blockquote><h3><span id="第四章-我家广大">第四章 我家广大</span></h3><blockquote><p>常为他人着想，世间就无逆境</p></blockquote><blockquote><p>在顺境时要收心，遇到逆境要放心</p></blockquote><blockquote><p>我们如何去面对别人的轻蔑和否定，这决定了自己的苦乐。若我们内心软弱，就像天上下石雨，小鸟无法承受；若我们内心有人生的目标与追求，有处世不惊的情绪与积极的态度，就像天上下花雨，飘落到大象身上。</p></blockquote><h3><span id="下篇-人生的十万个为什么">下篇 人生的十万个为什么</span></h3><blockquote><p>他人的态度决定不了你是什么样的人</p></blockquote><blockquote><p>太注重外在的看法，就成了他人的奴隶网友：请问法师，为啥做了一些事，心中总是会有怕被人指点和取笑的念头，充满焦虑。恳请法师教导！谢谢！学诚法师：太注重外在的看法，就成为了他人的奴隶。</p></blockquote><blockquote><p>学诚法师：在乎别人的看法，其实是在乎自己的形象。总是想保护自己、凸显自己，是内心虚弱的根源。唯有放下对自己的执着，才能放下对外界的依赖。</p></blockquote><blockquote><p>随缘消旧业，莫再造新殃网友：师父，一直诚心对人却遭到别人的不理解甚至报复，这是为什么呢？应该怎么做呢？学诚法师：随缘消旧业，莫再造新殃。</p></blockquote><blockquote><p>装聋作哑，风平浪静</p></blockquote><blockquote><p>学诚法师：感恩伤害过我们的人，因为他教会了我们坚强。</p></blockquote><blockquote><p>我们把排泄物、脏污都推给大地，大地却把他们吸收为养分，回报给我们甘美的果实。要做一个像大地一样的人。</p></blockquote><blockquote><p>外在的人和事早已过去，而内心还一直重现这种伤害，就是用别人的过错来惩罚自己——把仇恨记在心中，才是真正的伤害。冤家对头终有死亡的一天，而内心的烦恼若不除去，会一直伤害自己到永远。</p></blockquote><blockquote><p>抱怨是无能的表现，人人都知道有问题，要能够解决问题才是有价值的。</p></blockquote><blockquote><p>认识烦恼是修行的开始。顺境中多听闻佛法、积累资粮，逆境中思维佛法、随转修心、调伏烦恼。对这颗心的驾驭程度，就是修行的功夫。</p></blockquote><h3><span id="第六章-职场金刚经">第六章 职场金刚经</span></h3><blockquote><p>如果他说得有理，那就努力去改善自己；如果他说得无理，大家都会看得分明。每个人心中都有一杆秤，有人毁谤时，信任你的人依然会信任你；反过来说，即使大多数人都赞美，讨厌你的人依然会讨厌你。他人的好恶不足以作为我们生命的准绳，而决定自己苦乐的根本在于心中在意的事情。</p></blockquote><blockquote><p>对事不对人。对人，就有成见、有执着、有烦恼；对事，就好好处理事情。</p></blockquote><blockquote><p>上司对我不公平怎么办？网友：心中总是怨恨上司的不公平，如何去消除这种心理？学诚法师：吉凶祸福，是天主张；毁誉予夺，是人主张；主身行己，是我主张。他人做什么、如何做是他人的事，我要做什么、如何做是我的事。</p></blockquote><blockquote><p>把一切当作帮助自己成长的机会。大家说得对的，接受；说得不对的，练习增长自己的度量和包容。自己不上前“迎战”，挥来的拳头便如同打到虚空上，失去了对手。</p></blockquote><blockquote><p>不要和别人竞争，要和昨天的自己比较：是我自己要成长，与他人无关。</p></blockquote><blockquote><p>每一种说法，都是对应某一个问题而产生的，不是绝对的。</p></blockquote><h3><span id="第七章-格局决定命运">第七章 格局决定命运</span></h3><blockquote><p>不要把挫折当作结局，把它看作成长的财富。不要总是把“绝望”放在心里，视失败为畏途，这样的心态只会注定失败。人，不管怎么输，都不能输掉信心和志气，不能输掉希望和勇气。</p></blockquote><blockquote><p>人活着是为什么？这是人一生中最重要的问题。孟子曾说“人之异于禽兽者几希”，人与动物的基本需求都是生存、繁衍，但如果只是停留在此，就失去了生而为人的真正意义。人最特殊的一点是擅长思考，所以不会停留在“追求水草”的阶段，而是懂得去探寻生命的奥妙，追求自身的不断提升、进步。每个人的努力奋斗和整个人类的集体前进，无不源于内心深处不断提升自我的愿望。如何能够觉醒，能够实现生命的最大价值，就是生命的使命。</p></blockquote><blockquote><p>人生不是因为顺利而精彩，而是因为战胜磨难而辉煌！自我的成长是真正的成就，而不是外在的什么结果。</p></blockquote><blockquote><p>浮躁是因为看得太短，只注重眼前的小利或一时感受。在快节奏的工作、生活中，大家都容易不自觉的浮躁，都是在匆匆行路的过程中忘记了真正的目的地。要不断停下来反问自己：我这样做是为了什么？不断在内心提策、树立长远的大愿，宝贵的生命不应浪费在浮躁的泡沫中！</p></blockquote><blockquote><p>因为人一直在向外追逐，关注外境，常常忘记审视内心，迷失了自己。人不应该把快乐寄托在他人、他物上，要努力用高尚积极的精神充实自己的心灵；进一步，把心打开，多想他人的苦乐，少想自己的苦乐，去助人、利人，心便会充满力量。</p></blockquote><blockquote><p>放下执着，感恩生活的当下，就是100%的幸福。</p></blockquote><blockquote><p>佛教鼓励我们追求成功，关键是对“成功”的定义。佛教认为：一个人的成功，不是看外在的名利地位，而是看内心的自在坦然；不是看他得到了多少，而是看他付出了多少；不是看他自己有多幸福，而是看他令多少人得到了幸福。</p></blockquote><blockquote><p>佛教说的忍，绝非压抑、硬忍，而是用智慧来消融、用慈悲来转化。例如把打压视作激励，在逆境中培养谦卑。转换思维重点：不要总想着如何去对付逆境，而要想着如何提升自己。</p></blockquote><h3><span id="第八章-一切都只能放下">第八章 一切都只能放下</span></h3><blockquote><p>一般人认为，造恶能以行善抵消，仅仅是在行善或造恶的行为上去考虑，认为自己只要做了一些善事，就有“资本”继续造恶业，庸俗地以世俗的债务关系来理解：只要我有钱，欠多少债都能还。这样想本身就是邪见，是不懂得佛法。寓言中有“刻舟求剑”的愚人，在一个地方犯了错误，却想在其他地方来弥补，认为“行善可以抵消恶业”的人，就与这个愚人一样，没有抓住问题的核心。佛法讲，造业的核心在心，在动机，只有改变心，才能改变业。造了恶业，只有从心底里真正认识到这样做是错误的，产生痛悔之心，洗心革面，决不再造，才能真正“消业”</p></blockquote><blockquote><p>心中无有挂碍是放下，被逼无奈是懦弱。是放下还是懦弱，并不是由别人的看法决定的，而在于自己内心的强弱。大鹏鸟不屑于林间枝头的游戏，即使被小麻雀嘲笑，又岂会放在心上？只要自己足够强大，就不怕他人相欺。</p></blockquote>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;上篇-说好话积福报&quot;&gt;&lt;a href=&quot;#上篇-说好话积福报&quot; class=&quot;headerlink&quot; title=&quot;上篇 说好话积福报&quot;&gt;&lt;/a&gt;上篇 说好话积福报&lt;/h3&gt;&lt;blockquote&gt;
&lt;p&gt;智慧是什么呢？智慧就是当别人用戾气对你的时候，首先你要抱有一颗慈悲心，然后去寻找化解的办法。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;
&lt;p&gt;好好地修慈心、悲心、喜心、舍心。这些心念修好以后，我们说出来的话，肯定是出于好心，肯定是对方能接受的好话。&lt;/p&gt;
&lt;/blockquote&gt;
    
    </summary>
    
    
      <category term="读书笔记" scheme="http://landerqi.com/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/"/>
    
  </entry>
  
  <entry>
    <title>2018web开发者技能图谱</title>
    <link href="http://landerqi.com/2018/08/07/2018web%E5%BC%80%E5%8F%91%E8%80%85%E6%8A%80%E8%83%BD%E5%9B%BE%E8%B0%B1/"/>
    <id>http://landerqi.com/2018/08/07/2018web开发者技能图谱/</id>
    <published>2018-08-07T09:30:26.000Z</published>
    <updated>2019-09-25T03:11:50.737Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="2018web开发者技能图谱">2018web开发者技能图谱:</span></h3><p><img src="https://bookstorage.bs2dl.yy.com/26218_1569381011915480546.png"></p><span id="more"></span><h4><span id="资源推荐"><strong>资源推荐:</strong></span></h4><ul><li><a href="https://github.com/geeeeeeeeek/git-recipes">Git使用文档</a></li><li><a href="https://en.wikipedia.org/wiki/Secure_Shell">SSH</a></li><li><a href="https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol">HTTP</a></li><li><a href="https://en.wikipedia.org/wiki/HTTPS">HTTPS</a></li><li><a href="https://www.w3.org/International/questions/qa-what-is-encoding">Character Encodings</a></li><li><a href="https://github.com/">GitHub</a></li><li>终端使用：windows系统推荐<code>git bash</code>或者<a href="http://cmder.net/">cmder</a>, MacOs推荐<code>iTerm2</code></li><li>数据结构及算法：《算法图解》（正在看）</li><li>网络相关：《https权威指南》、《网络是怎么连接的》、《图解HTTP》</li></ul><h3><span id="前端图谱">前端图谱:</span></h3><p><img src="https://bookstorage.bs2dl.yy.com/26218_1569381055773698253.png"></p><h4><span id="资源推荐"><strong>资源推荐:</strong></span></h4><ul><li><a href="http://bonsaiden.github.io/JavaScript-Garden/zh/">javacript秘密花园</a></li><li><a href="https://ustbhuangyi.github.io/vue-analysis/">vuejs原码分析</a>, <a href="https://cn.vuejs.org/v2/guide/">vuejs官方文档</a></li><li><a href="http://react-china.org/">react</a></li><li><a href="https://hulufei.gitbooks.io/react-tutorial/content/introduction.html">react入门教程</a></li><li><a href="https://addyosmani.com/resources/essentialjsdesignpatterns/book/">javascript设计模式</a></li><li><a href="https://zhaoda.net/webpack-handbook/preface.html">模块系统</a></li><li>ES6: 《ES6标准入门》（阮一峰）</li></ul><h3><span id="后端图谱">后端图谱:</span></h3><p><img src="https://bookstorage.bs2dl.yy.com/26218_1569381090699713993.png"></p><h4><span id="资源推荐"><strong>资源推荐:</strong></span></h4><ul><li><a href="https://nodejs.org/en/">NodeJs</a></li><li><a href="https://expressjs.com/">express.js</a></li><li>Docker: 《第一本Docker书》</li></ul>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;2018web开发者技能图谱&quot;&gt;&lt;a href=&quot;#2018web开发者技能图谱&quot; class=&quot;headerlink&quot; title=&quot;2018web开发者技能图谱:&quot;&gt;&lt;/a&gt;2018web开发者技能图谱:&lt;/h3&gt;&lt;p&gt;&lt;img src=&quot;https://bookstorage.bs2dl.yy.com/26218_1569381011915480546.png&quot;&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="javascript" scheme="http://landerqi.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>javascript-patterns学习笔记（二）</title>
    <link href="http://landerqi.com/2018/07/10/javascript-patterns%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%88%E4%BA%8C%EF%BC%89/"/>
    <id>http://landerqi.com/2018/07/10/javascript-patterns学习笔记（二）/</id>
    <published>2018-07-10T07:39:02.000Z</published>
    <updated>2019-07-02T06:28:51.116Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="原始值的包装对象">原始值的包装对象</span></h3><p>__JavaScript中有五种原始类型：数字、字符串、布尔值、null和undefined。__除了null和undefined之外，其他三种都有对应的“包装对象”（wrapper objects）。可以通过内置构造函数来生成包装对象，Number()、String()、和Boolean()。</p><p>为了说明数字原始值和数字对象之间的区别，看一下下面这个例子：</p><figure class="highlight javascript"><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"><span class="comment">// a primitive number</span></span><br><span class="line"><span class="keyword">var</span> n = <span class="number">100</span>;</span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> n); <span class="comment">// &quot;number&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// a Number object</span></span><br><span class="line"><span class="keyword">var</span> nobj = <span class="keyword">new</span> <span class="built_in">Number</span>(<span class="number">100</span>);</span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> nobj); <span class="comment">// &quot;object&quot;</span></span><br></pre></td></tr></table></figure><span id="more"></span><p>包装对象带有一些有用的属性和方法，比如，数字对象就带有toFixed()和toExponential()之类的方法。字符串对象带有substring()、chatAt()和toLowerCase()等方法以及length属性。这些方法非常方便，和原始值相比，这让包装对象具备了一定优势。其实原始值也可以调用这些方法，因为原始值会首先转换为一个临时对象，如果转换成功，则调用包装对象的方法。</p><figure class="highlight reasonml"><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"><span class="comment">// a primitive string be used as an object</span></span><br><span class="line">var s = <span class="string">&quot;hello&quot;</span>;</span><br><span class="line">console.log(s.<span class="keyword">to</span><span class="constructor">UpperCase()</span>); <span class="comment">// &quot;HELLO&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// the value itself can act as an object</span></span><br><span class="line"><span class="string">&quot;monkey&quot;</span>.slice(<span class="number">3</span>, <span class="number">6</span>); <span class="comment">// &quot;key&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// same for numbers</span></span><br><span class="line">(<span class="number">22</span><span class="operator"> / </span><span class="number">7</span>).<span class="keyword">to</span><span class="constructor">Precision(3)</span>; <span class="comment">// &quot;3.14&quot;</span></span><br></pre></td></tr></table></figure><p>因为原始值可以根据需要转换成对象，这样的话，也不必为了用包装对象的方法而将原始值手动“包装”成对象。比如，不必使用new String(“hi”)，直接使用”hi”即可。</p><figure class="highlight haxe"><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"><span class="comment">// avoid these:</span></span><br><span class="line"><span class="keyword">var</span> s = <span class="keyword">new</span> <span class="type">String</span>(<span class="string">&quot;my string&quot;</span>);</span><br><span class="line"><span class="keyword">var</span> n = <span class="keyword">new</span> <span class="type">Number</span>(<span class="number">101</span>);</span><br><span class="line"><span class="keyword">var</span> b = <span class="keyword">new</span> <span class="type">Boolean</span>(<span class="literal">true</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// better and simpler:</span></span><br><span class="line"><span class="keyword">var</span> s = <span class="string">&quot;my string&quot;</span>;</span><br><span class="line"><span class="keyword">var</span> n = <span class="number">101</span>;</span><br><span class="line"><span class="keyword">var</span> b = <span class="literal">true</span>;</span><br></pre></td></tr></table></figure><p>不得不使用包装对象的一个原因是，有时我们需要对值进行扩充并保持值的状态。原始值毕竟不是对象，不能直接对其进行扩充（译注：比如1.property = 2会报错）。</p><figure class="highlight actionscript"><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"><span class="comment">// primitive string</span></span><br><span class="line"><span class="keyword">var</span> greet = <span class="string">&quot;Hello there&quot;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// primitive is converted to an object</span></span><br><span class="line"><span class="comment">// in order to use the split() method</span></span><br><span class="line">greet.split(<span class="string">&#x27; &#x27;</span>)[<span class="number">0</span>]; <span class="comment">// &quot;Hello&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="comment">// attemting to augment a primitive is not an error</span></span><br><span class="line">greet.smile = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// but it doesn&#x27;t actually work</span></span><br><span class="line"><span class="keyword">typeof</span> greet.smile; <span class="comment">// &quot;undefined&quot;</span></span><br></pre></td></tr></table></figure><p>在这段示例代码中，greet只是临时转换成了对象，以保证访问其属性/方法时不会出错。另一方面，如果greet通过new String()定义为一个对象，那么扩充smile属性就会按照期望的那样执行。对字符串、数字或布尔值的扩充并不常见，除非你清楚自己想要什么，否则不必使用包装对象。</p><p>当省略new时，包装器将传给它的参数转换为原始值：</p><figure class="highlight coffeescript"><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 class="keyword">typeof</span> <span class="built_in">Number</span>(<span class="number">1</span>); <span class="regexp">//</span> <span class="string">&quot;number&quot;</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="built_in">Number</span>(<span class="string">&quot;1&quot;</span>); <span class="regexp">//</span> <span class="string">&quot;number&quot;</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="built_in">Number</span>(<span class="keyword">new</span> <span class="built_in">Number</span>()); <span class="regexp">//</span> <span class="string">&quot;number&quot;</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="built_in">String</span>(<span class="number">1</span>); <span class="regexp">//</span> <span class="string">&quot;string&quot;</span></span><br><span class="line"><span class="keyword">typeof</span> <span class="built_in">Boolean</span>(<span class="number">1</span>); <span class="regexp">//</span> <span class="string">&quot;boolean&quot;</span></span><br></pre></td></tr></table></figure><h3><span id="error-对象">Error 对象</span></h3><p>JavaScript中有很多内置的Error构造函数，比如Error()、SyntaxError()，TypeError()等等，这些“错误”通常和throw语句一起使用。这些构造函数创建的错误对象包含这些属性：</p><h4><span id="name">name</span></h4><p>name属性是指创建这个对象的构造函数的名字，通常是“Error”，有时会有特定的名字比如“RangeError”</p><h4><span id="message">message</span></h4><p>创建这个对象时传入构造函数的字符串</p><p>错误对象还有其他一些属性，比如产生错误的行号和文件名，但这些属性是浏览器自行实现的，不同浏览器的实现也不一致，因此出于兼容性考虑，并不推荐使用这些属性。</p><p>另一方面，throw可以抛出任何对象，并不限于“错误对象”，因此你可以根据需要抛出自定义的对象。这些对象包含属性“name”和“message”或其他你希望传递给异常处理逻辑的信息，异常处理逻辑由catch语句指定。你可以灵活运用抛出的错误对象，将程序从错误状态恢复至正常状态。</p><figure class="highlight dts"><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"><span class="class">try </span>&#123;</span><br><span class="line">    <span class="comment">// something bad happened, throw an error</span></span><br><span class="line">    <span class="class">throw </span>&#123;</span><br><span class="line"><span class="symbol">        name:</span> <span class="string">&quot;MyErrorType&quot;</span>, <span class="comment">// custom error type</span></span><br><span class="line"><span class="symbol">        message:</span> <span class="string">&quot;oops&quot;</span>,</span><br><span class="line"><span class="symbol">        extra:</span> <span class="string">&quot;This was rather embarrassing&quot;</span>,</span><br><span class="line"><span class="symbol">        remedy:</span> genericErrorHandler <span class="comment">// who should handle it</span></span><br><span class="line">    &#125;;</span><br><span class="line">&#125; catch (e) &#123;</span><br><span class="line">    <span class="comment">// inform the user</span></span><br><span class="line">    alert(e.message); <span class="comment">// &quot;oops&quot;</span></span><br><span class="line"></span><br><span class="line">    <span class="comment">// gracefully handle the error</span></span><br><span class="line">    e.remedy(); <span class="comment">// calls genericErrorHandler()</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>通过new调用和省略new调用错误构造函数是一模一样的，他们都返回相同的错误对象。</strong></p><h3><span id="javascript的函数具有两个主要特性正是这两个特性让它们与众不同-第一个特性是函数是一等对象first-class-object第二个是函数提供作用域支持">JavaScript的函数具有两个主要特性，正是这两个特性让它们与众不同。第一个特性是，函数是一等对象（first-class object），第二个是函数提供作用域支持。</span></h3><h4><span id="函数是对象那么">函数是对象，那么：</span></h4><pre><code>+ 可以在程序执行时动态创建函数+ 可以将函数赋值给变量，可以将函数的引用拷贝至另一个变量，可以扩充函数，除了某些特殊场景外均可被删除。+ 可以将函数作为参数传入另一个函数，也可以被当作返回值返回。</code></pre><p>函数可以包含自己的属性和方法<br>对于一个函数A来说，首先它是对象，拥有属性和方法，其中某个属性碰巧是另一个函数B，B可以接受函数作为参数，假设这个函数参数为C，当执行B的时候，返回另一个函数D。乍一看这里有一大堆相互关联的函数。当你开始习惯函数的许多用法时，你会惊叹原来函数是如此强大、灵活并富有表现力。通常说来，一说到JavaScript的函数，我们首先认为它是对象，它具有一个可以“执行”的特性，也就是说我们可以“调用”这个函数。</p><p>我们通过new Function()构造器来生成一个函数，这时可以明显看出函数是对象：</p><figure class="highlight oxygene"><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 class="comment">// antipattern</span></span><br><span class="line"><span class="comment">// for demo purposes only</span></span><br><span class="line"><span class="keyword">var</span> <span class="keyword">add</span> = <span class="keyword">new</span> <span class="function"><span class="keyword">Function</span><span class="params">(<span class="string">&#x27;a, b&#x27;</span>, <span class="string">&#x27;return a + b&#x27;</span>)</span>;</span></span><br><span class="line"><span class="keyword">add</span>(<span class="number">1</span>, <span class="number">2</span>); <span class="comment">// returns 3</span></span><br></pre></td></tr></table></figure><p>在这段代码中，毫无疑问add()是一个对象，毕竟它是由构造函数创建的。这里并不推荐使用Function()构造器创建函数（和eval()一样糟糕），因为程序逻辑代码是以字符串的形式传入构造器的。这样的代码可读性差，写起来也很费劲，你不得不对逻辑代码中的引号做转义处理，并需要特别关注为了让代码保持一定的可读性而保留的空格和缩进。</p><h4><span id="__函数的第二个重要特性是它能提供作用域支持-__在javascript中没有块级作用域译注在javascript17中提供了块级作用域部分特性的支持可以通过let来声明块级作用域内的局部变量也就是说不能通过花括号来创建作用域javascript中只有函数作用域译注这里作者的表述只针对函数而言此外javascript还有全局作用域-在函数内所有通过var声明的变量都是局部变量在函数外部是不可见的-刚才所指花括号无法提供作用域支持的意思是说如果在if条件句内-或在for或while循环体内用var定义了变量这个变量并不是属于if语句或forwhile循环的局部变量而是属于它所在的函数-如果不在任何函数内部它会成为全局变量-在第二章里提到我们要减少对全局命名空间的污染那么使用函数则是控制变量的作用域的不二之选">__函数的第二个重要特性是它能提供作用域支持。__在JavaScript中没有块级作用域（译注：在JavaScript1.7中提供了块级作用域部分特性的支持，可以通过let来声明块级作用域内的“局部变量”），也就是说不能通过花括号来创建作用域，JavaScript中只有函数作用域（译注：这里作者的表述只针对函数而言，此外JavaScript还有全局作用域）。在函数内所有通过var声明的变量都是局部变量，在函数外部是不可见的。刚才所指花括号无法提供作用域支持的意思是说，如果在if条件句内、或在for或while循环体内用var定义了变量，这个变量并不是属于if语句或for（while）循环的局部变量，而是属于它所在的函数。如果不在任何函数内部，它会成为全局变量。在第二章里提到我们要减少对全局命名空间的污染，那么使用函数则是控制变量的作用域的不二之选。</span></h4><h3><span id="声明-vs-表达式命名与提前">声明 vs 表达式：命名与提前</span></h3><p>那么，到底应该用哪个呢？函数声明还是函数表达式？在不能使用函数声明语法的场景下，只能使用函数表达式了。下面这个例子中，我们给函数传入了另一个函数对象作为参数，以及给对象定义方法:</p><figure class="highlight awk"><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"><span class="regexp">//</span> this is a <span class="keyword">function</span> expression,</span><br><span class="line"><span class="regexp">//</span> pased as an argument to the <span class="keyword">function</span> `callMe`</span><br><span class="line">callMe(<span class="keyword">function</span> () &#123;</span><br><span class="line">    <span class="regexp">//</span> I am an unnamed <span class="keyword">function</span> expression</span><br><span class="line">    <span class="regexp">//</span> also known as an anonymous <span class="keyword">function</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="regexp">//</span> this is a named <span class="keyword">function</span> expression</span><br><span class="line">callMe(<span class="keyword">function</span> me() &#123;</span><br><span class="line">    <span class="regexp">//</span> I am a named <span class="keyword">function</span> expression</span><br><span class="line">    <span class="regexp">//</span> and my name is <span class="string">&quot;me&quot;</span></span><br><span class="line">&#125;);</span><br><span class="line"></span><br><span class="line"><span class="regexp">//</span> another <span class="keyword">function</span> expression</span><br><span class="line">var myobject = &#123;</span><br><span class="line">    say: <span class="keyword">function</span> () &#123;</span><br><span class="line">        <span class="regexp">//</span> I am a <span class="keyword">function</span> expression</span><br><span class="line">    &#125;</span><br><span class="line">&#125;;</span><br></pre></td></tr></table></figure><p><strong>函数声明只能出现在“程序代码”中，也就是说在别的函数体内或在全局。这个定义不能赋值给变量或属性，同样不能作为函数调用的参数。下面这个例子是函数声明的合法用法，这里所有的函数foo()，bar()和local()都使用函数声明来定义：</strong></p><figure class="highlight actionscript"><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"><span class="comment">// global scope</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">local</span><span class="params">()</span> </span>&#123;</span><br><span class="line">    <span class="comment">// local scope</span></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">bar</span><span class="params">()</span> </span>&#123;&#125;</span><br><span class="line">    <span class="keyword">return</span> bar;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h4><span id="函数的name属性">函数的name属性</span></h4><p>选择函数定义模式的另一个考虑是只读属性name的可用性。尽管标准规范中并未规定，但很多运行环境都实现了name属性，在函数声明和带有名字的函数表达式中是有name的属性定义的。在匿名函数表达式中，则不一定有定义，这个是和实现相关的，在IE中是无定义的，在Firefox和Safari中是有定义的，但是值为空字符串。</p><figure class="highlight awk"><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"><span class="keyword">function</span> foo() &#123;&#125; <span class="regexp">//</span> declaration</span><br><span class="line">var bar = <span class="keyword">function</span> () &#123;&#125;; <span class="regexp">//</span> expression</span><br><span class="line">var baz = <span class="keyword">function</span> baz() &#123;&#125;; <span class="regexp">//</span> named expression</span><br><span class="line"></span><br><span class="line">foo.name; <span class="regexp">//</span> <span class="string">&quot;foo&quot;</span></span><br><span class="line">bar.name; <span class="regexp">//</span> <span class="string">&quot;&quot;</span></span><br><span class="line">baz.name; <span class="regexp">//</span> <span class="string">&quot;baz&quot;</span></span><br></pre></td></tr></table></figure><p><strong>在Firebug或其他工具中调试程序时name属性非常有用，它可以用来显示当前正在执行的函数。同样可以通过name属性来递归的调用函数自身。如果你对这些场景不感兴趣，那么请尽可能的使用匿名函数表达式，这样会更简单、且冗余代码更少。</strong><br><strong>和函数声明相比而言，函数表达式的语法更能说明函数是一种对象，而不是某种特别的语言写法。</strong><br><strong>我们可以将一个带名字的函数表达式赋值给变量，变量名和函数名不同，这在技术上是可行的。比如：var foo = function bar(){};。然而，这种用法的行为在浏览器中的兼容性不佳（特别是IE中），因此并不推荐大家使用这种模式。</strong></p>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;原始值的包装对象&quot;&gt;&lt;a href=&quot;#原始值的包装对象&quot; class=&quot;headerlink&quot; title=&quot;原始值的包装对象&quot;&gt;&lt;/a&gt;原始值的包装对象&lt;/h3&gt;&lt;p&gt;__JavaScript中有五种原始类型：数字、字符串、布尔值、null和undefined。__除了null和undefined之外，其他三种都有对应的“包装对象”（wrapper objects）。可以通过内置构造函数来生成包装对象，Number()、String()、和Boolean()。&lt;/p&gt;
&lt;p&gt;为了说明数字原始值和数字对象之间的区别，看一下下面这个例子：&lt;/p&gt;
&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// a primitive number&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; n = &lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;console&lt;/span&gt;.log(&lt;span class=&quot;keyword&quot;&gt;typeof&lt;/span&gt; n); &lt;span class=&quot;comment&quot;&gt;// &amp;quot;number&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// a Number object&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; nobj = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Number&lt;/span&gt;(&lt;span class=&quot;number&quot;&gt;100&lt;/span&gt;);&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;console&lt;/span&gt;.log(&lt;span class=&quot;keyword&quot;&gt;typeof&lt;/span&gt; nobj); &lt;span class=&quot;comment&quot;&gt;// &amp;quot;object&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
    
    </summary>
    
    
      <category term="javascript" scheme="http://landerqi.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>javascript-patterns学习笔记（一）</title>
    <link href="http://landerqi.com/2018/07/09/javascript-patterns%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%88%E4%B8%80%EF%BC%89/"/>
    <id>http://landerqi.com/2018/07/09/javascript-patterns学习笔记（一）/</id>
    <published>2018-07-09T06:57:08.000Z</published>
    <updated>2019-07-02T06:28:51.115Z</updated>
    
    <content type="html"><![CDATA[<h4><span id="在本书中多次提到空对象blank-object和empty-object-这只是某种简称要知道javascript中根本不存在真正的空对象理解这一点至关重要-即使最简单的对象包含从objectprototype继承来的属性和方法-我们提到的空empty对象只是说这个对象没有自己的属性不考虑它是否有继承来的属性">在本书中多次提到“空对象”（“blank object”和“empty object”）。这只是某种简称，要知道JavaScript中根本不存在真正的空对象，理解这一点至关重要。即使最简单的{}对象包含从Object.prototype继承来的属性和方法。我们提到的“空（empty）对象”只是说这个对象没有自己的属性，不考虑它是否有继承来的属性。</span></h4><h3><span id="强制使用new的模式">强制使用new的模式</span></h3><p>我们知道，构造函数和普通的函数无异，只是通过new调用而已。那么如果调用构造函数时忘记new会发生什么呢？漏掉new不会产生语法错误也不会有运行时错误，但可能会造成逻辑错误，导致执行结果不符合预期。这是因为如果不写new的话，函数内的this会指向全局对象（在浏览器端this指向window）。<br>当构造函数内包含this.member之类的代码，并直接调用这个函数（省略new），实际会创建一个全局对象的属性member，可以通过window.member或member访问到它。这必然不是我们想要的结果，因为我们要努力确保全局命名空间的整洁干净。</p><figure class="highlight javascript"><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"><span class="comment">// constructor</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Waffle</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">this</span>.tastes = <span class="string">&quot;yummy&quot;</span>;</span><br><span class="line">&#125;</span><br><span class="line"><span class="comment">// a new object</span></span><br><span class="line"><span class="keyword">var</span> good_morning = <span class="keyword">new</span> Waffle();</span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> good_morning); <span class="comment">// &quot;object&quot;</span></span><br><span class="line"><span class="built_in">console</span>.log(good_morning.tastes); <span class="comment">// &quot;yummy&quot;</span></span><br><span class="line"><span class="comment">// antipattern:</span></span><br><span class="line"><span class="comment">// forgotten `new`</span></span><br><span class="line"><span class="keyword">var</span> good_morning = Waffle();</span><br><span class="line"><span class="built_in">console</span>.log(<span class="keyword">typeof</span> good_morning); <span class="comment">// &quot;undefined&quot;</span></span><br><span class="line"><span class="built_in">console</span>.log(<span class="built_in">window</span>.tastes); <span class="comment">// &quot;yummy&quot;</span></span><br></pre></td></tr></table></figure><p><strong>ECMAScript5中修正了这种非正常的行为逻辑。在严格模式中，this是不能指向全局对象的。如果在不支持ES5的JavaScript环境中，仍然后很多方法可以确保构造函数的行为即便在省略new调用时也不会出问题。</strong></p><span id="more"></span><h3><span id="使用that">使用that</span></h3><p>遵守命名约定的确能帮上一些忙，但约定毕竟不是强制，不能完全避免出错。这里给出了一种模式可以确保构造函数一定会按照构造函数的方式执行。不要将所有成员挂在this上，将它们挂在that上，并返回that。</p><figure class="highlight livescript"><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 class="keyword">function</span> Waffle() &#123;</span><br><span class="line"><span class="keyword">var</span> <span class="literal">that</span> = &#123;&#125;;</span><br><span class="line">    <span class="literal">that</span>.tastes = <span class="string">&quot;yummy&quot;</span>;</span><br><span class="line">    <span class="keyword">return</span> <span class="literal">that</span>;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>如果要创建简单的实例对象，甚至不需要定义一个局部变量that，可以直接返回一个对象直接量，就像这样：</p><figure class="highlight ada"><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 class="keyword">function</span> <span class="title">Waffle</span>() &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="type">&#123;</span></span><br><span class="line">        tastes: <span class="string">&quot;yummy&quot;</span></span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>不管用什么方式调用它（使用new或直接调用），它同都会返回一个实例对象：</p><figure class="highlight maxima"><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 class="built_in">var</span> <span class="built_in">first</span> = <span class="built_in">new</span> Waffle(),</span><br><span class="line">    <span class="built_in">second</span> = Waffle();</span><br><span class="line">console.<span class="built_in">log</span>(<span class="built_in">first</span>.tastes); // <span class="string">&quot;yummy&quot;</span></span><br><span class="line">console.<span class="built_in">log</span>(<span class="built_in">second</span>.tastes); // <span class="string">&quot;yummy&quot;</span></span><br></pre></td></tr></table></figure><p>这种模式的问题是丢失了原型，因此在Waffle()的原型上的成员不会继承到这些实例对象中。</p><p><strong>需要注意的是，这里用的that只是一种命名约定，that不是语言的保留字，可以将它替换为任何你喜欢的名字，比如self或me。</strong></p><p>4.调用自身的构造函数</p><p>为了解决上述模式的问题，能够让实例对象继承原型属性，我们使用下面的方法。在构造函数中首先检查this是否是构造函数的实例，如果不是，再通过new调用构造函数，并将new的结果返回：</p><figure class="highlight javascript"><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"><span class="function"><span class="keyword">function</span> <span class="title">Waffle</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line"></span><br><span class="line">    <span class="keyword">if</span> (!(<span class="built_in">this</span> <span class="keyword">instanceof</span> Waffle)) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="keyword">new</span> Waffle();</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="built_in">this</span>.tastes = <span class="string">&quot;yummy&quot;</span>;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">Waffle.prototype.wantAnother = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// testing invocations</span></span><br><span class="line"><span class="keyword">var</span> first = <span class="keyword">new</span> Waffle(),</span><br><span class="line">    second = Waffle();</span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(first.tastes); <span class="comment">// &quot;yummy&quot;</span></span><br><span class="line"><span class="built_in">console</span>.log(second.tastes); <span class="comment">// &quot;yummy&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="built_in">console</span>.log(first.wantAnother); <span class="comment">// true</span></span><br><span class="line"><span class="built_in">console</span>.log(second.wantAnother); <span class="comment">// true</span></span><br></pre></td></tr></table></figure><p>另一种检查实例的通用方法是使用arguments.callee，而不是直接将构造函数名写死在代码中：</p><figure class="highlight coffeescript"><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"><span class="keyword">if</span> (!(<span class="built_in">this</span> <span class="keyword">instanceof</span> <span class="built_in">arguments</span>.callee)) &#123;</span><br><span class="line">    <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">arguments</span>.callee();</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p><strong>这里需要说明的是，在任何函数内部都会自行创建一个arguments对象，它包含函数调用时传入的参数。同时arguments包含一个callee属性，指向它所在的正在被调用的函数。需要注意，ES5严格模式中是禁止使用arguments.callee的，因此最好对它的使用加以限制，并删除任何你能在代码中找到的实例（译注：这里作者的表述很委婉，其实作者更倾向于全面禁止使用arguments.callee）。</strong></p><h3><span id="检查是不是数组">检查是不是数组</span></h3><p>如果typeof的操作数是数组的话，将返回“object”。</p><figure class="highlight awk"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">console.log(typeof [<span class="number">1</span>, <span class="number">2</span>]); <span class="regexp">//</span> <span class="string">&quot;object&quot;</span></span><br></pre></td></tr></table></figure><p>这个结果勉强说得过去，毕竟数组是一种对象，但对我们用处不大。往往你需要知道一个值是不是真正的数组。你可能见到过这种检查数组的方法：检查length属性、检查数组方法比如slice()等等。但这些方法非常脆弱，非数组的对象也可以拥有这些同名的属性。还有些人使用instanceof Array来判断数组，但这种方法在某些版本的IE里的多个iframe的场景中会出问题（译注：原因就是在不同iframe中创建的数组不会相互共享其prototype属性）。</p><p>ECMAScript 5定义了一个新的方法Array.isArray()，如果参数是数组的话就返回true。比如：</p><figure class="highlight smali"><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">Array.isArray([]); // true</span><br><span class="line"></span><br><span class="line">// trying to fool the<span class="built_in"> check</span></span><br><span class="line"><span class="built_in"></span>// with an<span class="built_in"> array-like </span>object</span><br><span class="line">Array.isArray(&#123;</span><br><span class="line">    length: 1,</span><br><span class="line">    <span class="string">&quot;0&quot;</span>: 1,</span><br><span class="line">    slice: function () &#123;&#125;</span><br><span class="line">&#125;); // false</span><br></pre></td></tr></table></figure><p>如果你的开发环境不支持ECMAScript5，可以通过Object.prototype.toString()方法来代替。如调用toString的call()方法并传入数组上下文，将返回字符串“[object Array]”。如果传入对象上下文，则返回字符串“[object Object]”。因此可以这样做：</p><figure class="highlight ada"><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 class="keyword">if</span> (typeof <span class="keyword">Array</span>.isArray === <span class="string">&quot;undefined&quot;</span>) &#123;</span><br><span class="line">    <span class="keyword">Array</span>.isArray = <span class="keyword">function</span> <span class="title"></span>(arg) &#123;</span><br><span class="line">        <span class="keyword">return</span> <span class="type">Object.prototype.toString.call(arg)</span> === <span class="string">&quot;[object Array]&quot;</span>;</span><br><span class="line">    &#125;;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><h3><span id="json">JSON</span></h3><p>上文我们刚刚讨论过对象和数组直接量，你已经对此很熟悉了，现在我们将目光转向JSON。JSON（JavaScript Object Notation）是一种轻量级的数据交换格式。很多语言中都实现了JSON，特别是在JavaScript中。</p><p>JSON格式及其简单，它只是数组和对象直接量的混合写法，看一个JSON字符串的例子：</p><figure class="highlight json"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">&#123;<span class="attr">&quot;name&quot;</span>: <span class="string">&quot;value&quot;</span>, <span class="attr">&quot;some&quot;</span>: [<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>]&#125;</span><br></pre></td></tr></table></figure><p><strong>JSON和对象直接量在语法上的唯一区别是，合法的JSON属性名均用引号包含。而在对象直接量中，只有属性名是非法的标识符时采用引号包含，比如，属性名中包含空格{“first name”: “Dave”}。 在JSON字符串中，不能使用函数和正则表达式直接量。</strong></p><h4><span id="使用json">使用JSON</span></h4><p>在前面的章节中讲到，出于安全考虑，不推荐使用eval()来“粗糙的”解析JSON字符串。最好使用JSON.parse()方法，ES5中已经包含了这个方法，而且在现代浏览器的JavaScript引擎中已经内置支持JSON了。对于老旧的JavaScript引擎来说，你可以使用JSON.org所提供的JS文件 <a href="https://cdnjs.com/libraries/json2">https://cdnjs.com/libraries/json2</a> 来获得JSON对象和方法。</p><figure class="highlight lasso"><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"><span class="comment">// an input JSON string</span></span><br><span class="line"><span class="built_in">var</span> jstr = <span class="string">&#x27;&#123;&quot;mykey&quot;: &quot;my value&quot;&#125;&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// antipattern</span></span><br><span class="line"><span class="built_in">var</span> <span class="built_in">data</span> = eval(<span class="string">&#x27;(&#x27;</span> + jstr + <span class="string">&#x27;)&#x27;</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// preferred</span></span><br><span class="line"><span class="built_in">var</span> <span class="built_in">data</span> = JSON.parse(jstr);</span><br><span class="line"></span><br><span class="line">console.<span class="keyword">log</span>(<span class="built_in">data</span>.mykey); <span class="comment">// &quot;my value&quot;</span></span><br></pre></td></tr></table></figure><p>如果你已经在使用某个JavaScript库了，很可能库中提供了解析JSON的方法，就不必再额外引入JSON.org的库了，比如，如果你已经使用了YUI3，你可以这样：</p><figure class="highlight stata"><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"><span class="comment">// an input JSON string</span></span><br><span class="line"><span class="keyword">var</span> jstr = &#x27;&#123;<span class="string">&quot;mykey&quot;</span>: <span class="string">&quot;my value&quot;</span>&#125;&#x27;;</span><br><span class="line"></span><br><span class="line"><span class="comment">// parse the string and turn it into an object</span></span><br><span class="line"><span class="comment">// using a YUI instance</span></span><br><span class="line">YUI().<span class="keyword">use</span>(&#x27;json-<span class="keyword">parse</span>&#x27;, function (Y) &#123;</span><br><span class="line">    <span class="keyword">var</span> data = Y.JSON.<span class="keyword">parse</span>(jstr);</span><br><span class="line">    console.<span class="built_in">log</span>(data.mykey); <span class="comment">// &quot;my value&quot;</span></span><br><span class="line">&#125;);</span><br></pre></td></tr></table></figure><p>如果你使用的是jQuery，可以直接使用它提供的parseJSON()方法：</p><figure class="highlight lasso"><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 class="comment">// an input JSON string</span></span><br><span class="line"><span class="built_in">var</span> jstr = <span class="string">&#x27;&#123;&quot;mykey&quot;: &quot;my value&quot;&#125;&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="built_in">var</span> <span class="built_in">data</span> = jQuery.parseJSON(jstr);</span><br><span class="line">console.<span class="keyword">log</span>(<span class="built_in">data</span>.mykey); <span class="comment">// &quot;my value&quot;</span></span><br></pre></td></tr></table></figure><p>和JSON.parse()方法相对应的是JSON.stringify()。它将对象或数组（或任何原始值）转换为JSON字符串。</p><figure class="highlight livescript"><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"><span class="keyword">var</span> dog = &#123;</span><br><span class="line">    name: <span class="string">&quot;Fido&quot;</span>,</span><br><span class="line">    dob:<span class="keyword">new</span> <span class="built_in">Date</span>(),</span><br><span class="line">    legs:[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line"><span class="keyword">var</span> jsonstr = <span class="built_in">JSON</span>.stringify(dog);</span><br><span class="line"></span><br><span class="line"><span class="regexp">// jsonstr is now:</span></span><br><span class="line"><span class="regexp">//</span> &#123;<span class="string">&quot;name&quot;</span>:<span class="string">&quot;Fido&quot;</span>,<span class="string">&quot;dob&quot;</span>:<span class="string">&quot;2010-04-11T22:36:22.436Z&quot;</span>,<span class="string">&quot;legs&quot;</span>:[<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>]&#125;</span><br></pre></td></tr></table></figure>]]></content>
    
    <summary type="html">
    
      &lt;h4 id=&quot;在本书中多次提到“空对象”（“blank-object”和“empty-object”）。这只是某种简称，要知道JavaScript中根本不存在真正的空对象，理解这一点至关重要。即使最简单的-对象包含从Object-prototype继承来的属性和方法。我们提到的“空（empty）对象”只是说这个对象没有自己的属性，不考虑它是否有继承来的属性。&quot;&gt;&lt;a href=&quot;#在本书中多次提到“空对象”（“blank-object”和“empty-object”）。这只是某种简称，要知道JavaScript中根本不存在真正的空对象，理解这一点至关重要。即使最简单的-对象包含从Object-prototype继承来的属性和方法。我们提到的“空（empty）对象”只是说这个对象没有自己的属性，不考虑它是否有继承来的属性。&quot; class=&quot;headerlink&quot; title=&quot;在本书中多次提到“空对象”（“blank object”和“empty object”）。这只是某种简称，要知道JavaScript中根本不存在真正的空对象，理解这一点至关重要。即使最简单的{}对象包含从Object.prototype继承来的属性和方法。我们提到的“空（empty）对象”只是说这个对象没有自己的属性，不考虑它是否有继承来的属性。&quot;&gt;&lt;/a&gt;在本书中多次提到“空对象”（“blank object”和“empty object”）。这只是某种简称，要知道JavaScript中根本不存在真正的空对象，理解这一点至关重要。即使最简单的{}对象包含从Object.prototype继承来的属性和方法。我们提到的“空（empty）对象”只是说这个对象没有自己的属性，不考虑它是否有继承来的属性。&lt;/h4&gt;&lt;h3 id=&quot;强制使用new的模式&quot;&gt;&lt;a href=&quot;#强制使用new的模式&quot; class=&quot;headerlink&quot; title=&quot;强制使用new的模式&quot;&gt;&lt;/a&gt;强制使用new的模式&lt;/h3&gt;&lt;p&gt;我们知道，构造函数和普通的函数无异，只是通过new调用而已。那么如果调用构造函数时忘记new会发生什么呢？漏掉new不会产生语法错误也不会有运行时错误，但可能会造成逻辑错误，导致执行结果不符合预期。这是因为如果不写new的话，函数内的this会指向全局对象（在浏览器端this指向window）。&lt;br&gt;当构造函数内包含this.member之类的代码，并直接调用这个函数（省略new），实际会创建一个全局对象的属性member，可以通过window.member或member访问到它。这必然不是我们想要的结果，因为我们要努力确保全局命名空间的整洁干净。&lt;/p&gt;
&lt;figure class=&quot;highlight javascript&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;1&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;2&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;3&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;4&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;5&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;6&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;7&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;8&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;9&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;10&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;11&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;12&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;13&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;td class=&quot;code&quot;&gt;&lt;pre&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// constructor&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Waffle&lt;/span&gt;(&lt;span class=&quot;params&quot;&gt;&lt;/span&gt;) &lt;/span&gt;&amp;#123;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;    &lt;span class=&quot;built_in&quot;&gt;this&lt;/span&gt;.tastes = &lt;span class=&quot;string&quot;&gt;&amp;quot;yummy&amp;quot;&lt;/span&gt;;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&amp;#125;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// a new object&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; good_morning = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Waffle();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;console&lt;/span&gt;.log(&lt;span class=&quot;keyword&quot;&gt;typeof&lt;/span&gt; good_morning); &lt;span class=&quot;comment&quot;&gt;// &amp;quot;object&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;console&lt;/span&gt;.log(good_morning.tastes); &lt;span class=&quot;comment&quot;&gt;// &amp;quot;yummy&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// antipattern:&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;comment&quot;&gt;// forgotten `new`&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;var&lt;/span&gt; good_morning = Waffle();&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;console&lt;/span&gt;.log(&lt;span class=&quot;keyword&quot;&gt;typeof&lt;/span&gt; good_morning); &lt;span class=&quot;comment&quot;&gt;// &amp;quot;undefined&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;span class=&quot;line&quot;&gt;&lt;span class=&quot;built_in&quot;&gt;console&lt;/span&gt;.log(&lt;span class=&quot;built_in&quot;&gt;window&lt;/span&gt;.tastes); &lt;span class=&quot;comment&quot;&gt;// &amp;quot;yummy&amp;quot;&lt;/span&gt;&lt;/span&gt;&lt;br&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/figure&gt;
&lt;p&gt;&lt;strong&gt;ECMAScript5中修正了这种非正常的行为逻辑。在严格模式中，this是不能指向全局对象的。如果在不支持ES5的JavaScript环境中，仍然后很多方法可以确保构造函数的行为即便在省略new调用时也不会出问题。&lt;/strong&gt;&lt;/p&gt;
    
    </summary>
    
    
      <category term="javascript" scheme="http://landerqi.com/tags/javascript/"/>
    
  </entry>
  
  <entry>
    <title>shell-git常用命令</title>
    <link href="http://landerqi.com/2018/06/29/shell-git%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/"/>
    <id>http://landerqi.com/2018/06/29/shell-git常用命令/</id>
    <published>2018-06-29T08:48:11.000Z</published>
    <updated>2019-10-31T03:21:21.996Z</updated>
    
    <content type="html"><![CDATA[<h3><span id="shell常用命令">shell–常用命令</span></h3><ol><li>查询npm 依赖： npm ls -g –depth=1 2&gt;/dev/null | grep generator-</li></ol><ul><li>‘npm ls -g’列出依赖，通常是一个树状结构；</li><li>‘–depth=1’ 意思是只列出一层；</li><li> ‘2&gt;/dev/null’  &gt;表示重定向，在bash里面单独的1表示标准输出，2表示标准错误，/dev/null代表空设备文件，这句就表示在执行npm ls -g的时候有错误消息就重定向到空设备文件上，其实就是在输出中过滤了错误消息；</li><li>‘｜’ 表示通道，用来将上一个命令的输出内容作为下一个命令的输入内容;</li><li> ‘grep generator-‘表示在前面的输出结果中检索’generator’。</li></ul><ol><li><strong>brew update &amp;&amp; brew upgrade &amp;&amp; brew cleanup</strong></li><li> <strong>复制某文件夹下全部内容到另一文件夹，注意’.’这个是必须的，cp -a fold1/. fold2/</strong></li></ol><ul><li>windows: <strong>xcopy www backup /exclude:except.txt</strong> or <strong>robocopy SOURCE DEST /mir /xd node_modules</strong></li><li>linux: <strong>rsync -av –progress sourcefolder /destinationfolder –exclude thefoldertoexclude</strong></li></ul><ol><li><strong>windows关闭nginx:  taskkill /F /IM nginx.exe</strong></li><li><strong>windows查询nginx是否启动:  tasklist /fi “imagename eq nginx.exe”</strong></li><li><strong>查到端口占用：NETSTAT.EXE -aon|findstr “3002”</strong></li><li><strong>结束端口占用进程：taskkill.exe /f /t /im 10768</strong></li><li><strong>如何使npm intall 不需要输入 sudo: 为当前账户添加node_modules目录读写权限即可。sudo chown -R $(whoami) ~/.npm</strong></li></ol><span id="more"></span><h3><span id="git常用命令">git–常用命令</span></h3><ol><li><strong>新建本地分支，将远程分支提取出来： git checkout -t origin/2.0.0</strong></li><li><strong>To delete a local branch: git branch -d the_local_branch</strong></li><li><strong>To remove a remote branch: git push origin –delete the_remote_branch</strong></li><li><strong>将你的git协议由https变为ssh: git remote set-url origin <a href="mailto:&#x67;&#x69;&#x74;&#64;&#103;&#x69;&#116;&#104;&#117;&#x62;&#46;&#99;&#x6f;&#x6d;">&#x67;&#x69;&#x74;&#64;&#103;&#x69;&#116;&#104;&#117;&#x62;&#46;&#99;&#x6f;&#x6d;</a>:youraccount/yourproject.git</strong></li><li><strong>查看某次提交：</strong><figure class="highlight mipsasm"><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></pre></td><td class="code"><pre><span class="line"><span class="comment"># 查看某次提交修改的文件</span></span><br><span class="line">git <span class="keyword">show </span>COMMIT</span><br><span class="line">git <span class="keyword">diff </span>COMMIT^!</span><br><span class="line"></span><br><span class="line"><span class="comment"># 对比当前版本和&quot;COMMTI&quot;版本文件差异</span></span><br><span class="line">git <span class="keyword">diff </span>COMMIT</span><br></pre></td></tr></table></figure></li><li><strong>show log</strong>:<figure class="highlight shell"><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">git log --graph</span><br><span class="line">git log --graph --oneline --all</span><br><span class="line">git log --graph --pretty=oneline --abbrev-commit | tig # tig只查看，不会输出在shell</span><br><span class="line">git log --graph --pretty=oneline --abbrev-commit</span><br><span class="line"><span class="meta"></span></span><br><span class="line"><span class="meta">#</span><span class="bash"> 或者加个别名到全局配置</span></span><br><span class="line">git config --global alias.tree &quot;log --graph --decorate --pretty=oneline --abbrev-commit&quot;</span><br><span class="line"><span class="meta">#</span><span class="bash"> 就可以直接使用</span></span><br><span class="line">git tree</span><br></pre></td></tr></table></figure></li><li><strong>关联到新的 git 仓库地址:</strong><br>如果有<code>.git</code>文件夹，先 <code>rm -rf .git</code><figure class="highlight armasm"><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 class="symbol">git</span> init</span><br><span class="line"><span class="symbol">git</span> remote <span class="keyword">add</span> origin https:<span class="comment">//github.com/&#123;your_project&#125;.git</span></span><br><span class="line"><span class="symbol">git</span> <span class="keyword">add</span> .</span><br><span class="line"><span class="symbol">git</span> commit -m <span class="string">&quot;Initial commit&quot;</span></span><br><span class="line"><span class="symbol">git</span> <span class="keyword">push</span> -u origin master</span><br></pre></td></tr></table></figure></li></ol>]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;shell–常用命令&quot;&gt;&lt;a href=&quot;#shell–常用命令&quot; class=&quot;headerlink&quot; title=&quot;shell–常用命令&quot;&gt;&lt;/a&gt;shell–常用命令&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;查询npm 依赖： npm ls -g –depth=1 2&amp;gt;/dev/null | grep generator-&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;‘npm ls -g’列出依赖，通常是一个树状结构；&lt;/li&gt;
&lt;li&gt;‘–depth=1’ 意思是只列出一层；&lt;/li&gt;
&lt;li&gt; ‘2&amp;gt;/dev/null’  &amp;gt;表示重定向，在bash里面单独的1表示标准输出，2表示标准错误，/dev/null代表空设备文件，这句就表示在执行npm ls -g的时候有错误消息就重定向到空设备文件上，其实就是在输出中过滤了错误消息；&lt;/li&gt;
&lt;li&gt;‘｜’ 表示通道，用来将上一个命令的输出内容作为下一个命令的输入内容;&lt;/li&gt;
&lt;li&gt; ‘grep generator-‘表示在前面的输出结果中检索’generator’。&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;brew update &amp;amp;&amp;amp; brew upgrade &amp;amp;&amp;amp; brew cleanup&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;复制某文件夹下全部内容到另一文件夹，注意’.’这个是必须的，cp -a fold1/. fold2/&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;windows: &lt;strong&gt;xcopy www backup /exclude:except.txt&lt;/strong&gt; or &lt;strong&gt;robocopy SOURCE DEST /mir /xd node_modules&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;linux: &lt;strong&gt;rsync -av –progress sourcefolder /destinationfolder –exclude thefoldertoexclude&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;windows关闭nginx:  taskkill /F /IM nginx.exe&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;windows查询nginx是否启动:  tasklist /fi “imagename eq nginx.exe”&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;查到端口占用：NETSTAT.EXE -aon|findstr “3002”&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结束端口占用进程：taskkill.exe /f /t /im 10768&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;如何使npm intall 不需要输入 sudo: 为当前账户添加node_modules目录读写权限即可。sudo chown -R $(whoami) ~/.npm&lt;/strong&gt;&lt;/li&gt;
&lt;/ol&gt;
    
    </summary>
    
    
      <category term="工具" scheme="http://landerqi.com/tags/%E5%B7%A5%E5%85%B7/"/>
    
      <category term="git" scheme="http://landerqi.com/tags/git/"/>
    
  </entry>
  
</feed>
