-
Notifications
You must be signed in to change notification settings - Fork 14
/
Copy pathReact-16-8-6-版本存在内存泄露.html
1 lines (1 loc) · 29.7 KB
/
React-16-8-6-版本存在内存泄露.html
1
<!doctype html><html class="theme-next mist"><head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1"><meta name="google-site-verification" content="PBwskePkFkRAnqisXEBN7FyYihV0DkOHyvEC2eDt6Gg"><meta name="referrer" content="never"><script src="/lib/pace/pace.min.js?v=1.0.2"></script><link href="/lib/pace/pace-theme-minimal.min.css?v=1.0.2" rel="stylesheet"><meta http-equiv="Cache-Control" content="no-transform"><meta http-equiv="Cache-Control" content="no-siteapp"><meta name="baidu-site-verification" content="haLEFmuOYV"><script>!function(e,t,o,c,i,a,n){e.DaoVoiceObject=i,e[i]=e[i]||function(){(e[i].q=e[i].q||[]).push(arguments)},e[i].l=1*new Date,a=t.createElement(o),n=t.getElementsByTagName(o)[0],a.async=1,a.src=c,a.charset="utf-8",n.parentNode.insertBefore(a,n)}(window,document,"script",("https:"==document.location.protocol?"https:":"http:")+"//widget.daovoice.io/widget/0f81ff2f.js","daovoice"),daovoice("init",{app_id:"0f81ff2f"}),daovoice("update")</script><link href="/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css"><link href="/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css"><link href="/css/main.css?v=5.0.2" rel="stylesheet" type="text/css"><meta name="keywords" content="内存泄漏, react"><link rel="alternate" href="/atom.xml" title="Moorez" type="application/atom+xml"><link rel="shortcut icon" type="image/x-icon" href="/images/favicon.ico?v=5.0.2"><meta name="description" content="发现这个React 内存泄露问题是某一天的晚上一直开着直播页,直播页用的 react 版本是 16.8.6,到了早上跳到这个页面的时候,控制台有点卡,怀疑是有内存泄露,于是就开始分析这个直播页面。"><meta name="keywords" content="内存泄漏, react"><meta property="og:type" content="article"><meta property="og:title" content="React 16.8.6 版本存在内存泄露"><meta property="og:url" content="http://www.shenzekun.cn/React-16-8-6-版本存在内存泄露.html"><meta property="og:site_name" content="Moorez"><meta property="og:description" content="发现这个React 内存泄露问题是某一天的晚上一直开着直播页,直播页用的 react 版本是 16.8.6,到了早上跳到这个页面的时候,控制台有点卡,怀疑是有内存泄露,于是就开始分析这个直播页面。"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-fbb208fd19c5c448?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-c9d26f57023c0ef2?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-a7c964ac04ef30bf?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-f0d68a7fe4d37614?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-195ccdce44c67697?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-acdf0573456b793d?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-f35f034aa9448df6?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-f49a3e0bdf51eebf?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-d6eea6ef25193edf?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-04531de57817c1b7?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-a0058e635a81f86e?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:image" content="https://upload-images.jianshu.io/upload_images/5308475-fd4ccff974f0da7b?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><meta property="og:updated_time" content="2020-04-17T17:05:22.607Z"><meta name="twitter:card" content="summary"><meta name="twitter:title" content="React 16.8.6 版本存在内存泄露"><meta name="twitter:description" content="发现这个React 内存泄露问题是某一天的晚上一直开着直播页,直播页用的 react 版本是 16.8.6,到了早上跳到这个页面的时候,控制台有点卡,怀疑是有内存泄露,于是就开始分析这个直播页面。"><meta name="twitter:image" content="https://upload-images.jianshu.io/upload_images/5308475-fbb208fd19c5c448?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240"><script type="text/javascript" id="hexo.configuration">var NexT=window.NexT||{},CONFIG={scheme:"Mist",sidebar:{position:"left",display:"post"},fancybox:!0,motion:!1,duoshuo:{userId:"0",author:"Author"}}</script><link rel="canonical" href="http://www.shenzekun.cn/React-16-8-6-版本存在内存泄露.html"><title>React 16.8.6 版本存在内存泄露 | Moorez</title></head><body itemscope itemtype="//schema.org/WebPage" lang="zh-Hans"><div class="container one-collumn sidebar-position-left page-post-detail"><div class="headband"></div><a href="https://github.com/shenzekun" class="github-corner" aria-label="View source on Github"><svg width="92" height="92" viewBox="0 0 250 250" style="fill:#151513;color:#fff;position:absolute;top:0;border:0;right:0" aria-hidden="true"><path d="M0 0 115 115 130 115 142 142 250 250 250 0Z"></path><path d="M128.3 109C113.8 99.7 119 89.6 119 89.6 122 82.7 120.5 78.6 120.5 78.6 119.2 72 123.4 76.3 123.4 76.3 127.3 80.9 125.5 87.3 125.5 87.3 122.9 97.6 130.6 101.9 134.4 103.2" fill="currentColor" style="transform-origin:130px 106px" class="octo-arm"></path><path d="M115 115C114.9 115.1 118.7 116.5 119.8 115.4L133.7 101.6C136.9 99.2 139.9 98.4 142.2 98.6 133.8 88 127.5 74.4 143.8 58 148.5 53.4 154 51.2 159.7 51 160.3 49.4 163.2 43.6 171.4 40.1 171.4 40.1 176.1 42.5 178.8 56.2 183.1 58.6 187.2 61.8 190.9 65.4 194.5 69 197.7 73.2 200.1 77.6 213.8 80.2 216.3 84.9 216.3 84.9 212.7 93.1 206.9 96 205.4 96.6 205.1 102.4 203 107.8 198.3 112.5 181.9 128.9 168.3 122.5 157.7 114.1 157.9 116.9 156.7 120.9 152.7 124.9L141 136.5C139.8 137.7 141.6 141.9 141.8 141.8Z" fill="currentColor" class="octo-body"></path></svg></a><style>.github-corner:hover .octo-arm{animation:octocat-wave 560ms ease-in-out}@keyframes octocat-wave{0%,100%{transform:rotate(0)}20%,60%{transform:rotate(-25deg)}40%,80%{transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm{animation:none}.github-corner .octo-arm{animation:octocat-wave 560ms ease-in-out}}</style><header id="header" class="header" itemscope itemtype="//schema.org/WPHeader"><div class="header-inner"><div class="site-meta"><div class="custom-logo-site-title"><a href="/" class="brand" rel="start"><span class="logo-line-before"><i></i></span> <span class="site-title">Moorez</span><span class="logo-line-after"><i></i></span></a></div><p class="site-subtitle"></p></div><div class="site-nav-toggle"><button><span class="btn-bar"></span><span class="btn-bar"></span><span class="btn-bar"></span></button></div><nav class="site-nav"><ul id="menu" class="menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="menu-item-icon fa fa-fw fa-home"></i><br>首页</a></li><li class="menu-item menu-item-categories"><a href="/categories" rel="section"><i class="menu-item-icon fa fa-fw fa-th"></i><br>分类</a></li><li class="menu-item menu-item-about"><a href="/about" rel="section"><i class="menu-item-icon fa fa-fw fa-user"></i><br>关于</a></li><li class="menu-item menu-item-archives"><a href="/archives" rel="section"><i class="menu-item-icon fa fa-fw fa-archive"></i><br>归档</a></li><li class="menu-item menu-item-tags"><a href="/tags" rel="section"><i class="menu-item-icon fa fa-fw fa-tags"></i><br>标签</a></li><li class="menu-item menu-item-search"><a href="javascript:;" class="popup-trigger"><i class="menu-item-icon fa fa-search fa-fw"></i><br>搜索</a></li></ul><div class="site-search"><div class="popup"><span class="search-icon fa fa-search"></span> <input type="text" id="local-search-input"><div id="local-search-result"></div><span class="popup-btn-close">close</span></div></div></nav></div></header><main id="main" class="main"><div class="main-inner"><div class="content-wrap"><div id="content" class="content"><div id="posts" class="posts-expand"><article class="post post-type-normal" itemscope itemtype="http://schema.org/Article"><link itemprop="mainEntityOfPage" href="http://www.shenzekun.cn/React-16-8-6-版本存在内存泄露.html"><span hidden itemprop="author" itemscope itemtype="http://schema.org/Person"><meta itemprop="name" content="shenzekun"><meta itemprop="description" content=""><meta itemprop="image" content="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/avatar1.jpg"></span><span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization"><meta itemprop="name" content="Moorez"></span><header class="post-header"><h1 class="post-title" itemprop="name headline">React 16.8.6 版本存在内存泄露</h1><div class="post-meta"><span class="post-time"><span class="post-meta-item-icon"><i class="fa fa-calendar-o"></i></span> <span class="post-meta-item-text">发表于</span> <time itemprop="dateCreated" datetime="2020-04-18T01:01:26+08:00" content="2020-04-18">2020-04-18</time></span> <span class="post-category"> | <span class="post-meta-item-icon"><i class="fa fa-folder-o"></i></span> <span class="post-meta-item-text">分类于</span> <span itemprop="about" itemscope itemtype="https://schema.org/Thing"><a href="/categories/前端/" itemprop="url" rel="index"><span itemprop="name">前端</span></a></span></span> <span id="/React-16-8-6-版本存在内存泄露.html" class="leancloud_visitors" data-flag-title="React 16.8.6 版本存在内存泄露"> | <span class="post-meta-item-icon"><i class="fa fa-eye"></i></span> <span class="post-meta-item-text">热度</span><span class="leancloud-visitors-count"></span> <span>℃</span></span><div class="post-wordcount"><span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-file-word-o"></i></span> <span class="post-meta-item-text">字数统计</span> <span title="字数统计">883 字</span> <span class="post-meta-divider">|</span><span class="post-meta-item-icon"><i class="fa fa-clock-o"></i></span> <span class="post-meta-item-text">阅读时长</span> <span title="阅读时长">3 分钟</span></div></div></header><div class="post-body" itemprop="articleBody"><hr><blockquote><p>发现这个React 内存泄露问题是某一天的晚上一直开着直播页,直播页用的 react 版本是 16.8.6,到了早上跳到这个页面的时候,控制台有点卡,怀疑是有内存泄露,于是就开始分析这个直播页面。</p></blockquote><a id="more"></a><h3 id="分析"><a href="#分析" class="headerlink" title="分析"></a>分析</h3><p>打开控制台 <code>performance</code> 面板点击开始录制,如下:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-fbb208fd19c5c448?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>从上图可以发现在这时间内, nodes 节点一直在增长,很有可能发生了内存泄露。</p><p>我们来到 <code>memory</code> 面板分析内存变化:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-c9d26f57023c0ef2?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><blockquote><p>注:上图的蓝色线条表示在时间轴的最后该对象依旧存在,灰色线条则说明对象在时间轴内被分配,但是已经被gc(垃圾回收)了。</p></blockquote><p>上图都是点击 gc 再进行记录的,但是上图还有很多蓝色线条,而且内存一直往上涨,很明显的内存泄露问题,那会是什么导致内存泄露的呢?</p><p>很快发现这里有个 bi 的东西居然占了 31%的大小:<br><img src="https://upload-images.jianshu.io/upload_images/5308475-a7c964ac04ef30bf?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt="image"></p><p>这个 bi 是用来干嘛的?展开 bi ,鼠标悬浮在 bi 某处:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-f0d68a7fe4d37614?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>发现这个节点是直播间里的进房消息,里面是 react 存的 <code>FiberNode</code> 节点,观察了一下里面这些 bi 基本上都是消息元素。</p><p>选择 <code>summary</code>,选出<code>Detached</code> (分离)的元素:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-195ccdce44c67697?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><code>Detached HTMLDivElement</code> 居然有41429个,展开,鼠标悬浮:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-acdf0573456b793d?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>还是消息信息,说明是这个导致 bi 增加的。我们继续展开:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-f35f034aa9448df6?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>从上图看 react 会保留消息的上下兄弟节点的引用,而且保留的引用层级有点深,各个节点嵌套依赖,导致一直存在内存里:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-f49a3e0bdf51eebf?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>仔细查下了项目消息相关代码,发现并不会存在有内存泄露的操作。这里简单说下渲染消息的逻辑,消息有进房消息,聊天消息,礼物消息等等,消息展示会根据 messages 数组里面的类型去渲染不同的消息。messages 数组不会无限增长,控制在 100 个,超过就删掉第一个元素,保证维持100个元素渲染消息,但是从上图来看,这些分离的元素并没有被 react 完全删除,还保存在内存里,查了下 React 的 Issue,并查了相关文章,发现有不少人遇到这个问题:</p><ul><li><a href="https://github.com/facebook/react/issues/16138" target="_blank" rel="external">https://github.com/facebook/react/issues/16138</a></li><li><a href="https://github.com/facebook/react/issues/14732" target="_blank" rel="external">https://github.com/facebook/react/issues/14732</a></li><li><a href="https://github.com/facebook/react/issues/18116" target="_blank" rel="external">https://github.com/facebook/react/issues/18116</a></li><li><a href="https://blog.discordapp.com/discord-react-memory-leak-565c89763e8" target="_blank" rel="external">Investigating Discord’s React Memory Leak - Discord Blog</a></li></ul><p>React 核心成员 Dan 给出的解决办法是升级到 16.9.0。</p><p>这里将项目 React 和 React-dom 版本升级16.9.0,<br>发现 FiberNode 节点还是会一直增加。。。</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-d6eea6ef25193edf?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-04531de57817c1b7?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>继续查看Issue 发现,React 版本 <code>0.0.0-241c4467e</code> 修复了这个问题。<br><a href="https://github.com/facebook/react/issues/18066" target="_blank" rel="external">Bug: Detached DOM node memory leak · Issue #18066 · facebook/react · GitHub</a></p><p>这个版本的 mr 已经合并在 React master 上<br><a href="https://github.com/facebook/react/pull/17666" target="_blank" rel="external">Null stateNode after unmount by bvaughn · Pull Request #17666 · facebook/react · GitHub</a></p><p>这个 mr 是 2019 年 12 月 20 号合并的,2019 年 12 月 20 号之后的版本是 16.13.0,这里将项目直接升级到 16.13.1,然后查看 node 节点:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-a0058e635a81f86e?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>发现 node 节点可以降下来了,查看 <code>memory</code> 面板:</p><p><img src="https://upload-images.jianshu.io/upload_images/5308475-fd4ccff974f0da7b?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240" alt=""></p><p>对比<code>Snapshot 5</code>,分离的元素没有新增,说明这个版本基本修复了这个问题。</p><h3 id="结论"><a href="#结论" class="headerlink" title="结论"></a>结论</h3><p>React <strong>16.8.6</strong> (<strong>16.2.5到16.12.0</strong> 可能会有,这些版本没有验证,但是 issue 里面有人遇到)的版本会存在内存泄露问题,建议升级 React 到 <strong>16.13.0</strong> 以上。</p></div><div><div><div style="text-align:center;color:#ccc;font-size:14px">-------------本文结束<i class="fa fa-paw"></i>感谢您的阅读-------------</div></div></div><div><div class="my_post_copyright"><script src="//cdn.bootcss.com/clipboard.js/1.5.10/clipboard.min.js"></script><script src="https://cdn.bootcss.com/jquery/2.0.0/jquery.min.js"></script><script src="https://unpkg.com/sweetalert/dist/sweetalert.min.js"></script><p><span>本文标题:</span><a href="/React-16-8-6-版本存在内存泄露.html">React 16.8.6 版本存在内存泄露</a></p><p><span>文章作者:</span><a href="/" title="访问 shenzekun 的个人博客">shenzekun</a></p><p><span>发布时间:</span>2020年04月18日 - 01:01</p><p><span>最后更新:</span>2020年04月18日 - 01:05</p><p><span>原始链接:</span><a href="/React-16-8-6-版本存在内存泄露.html" title="React 16.8.6 版本存在内存泄露">http://www.shenzekun.cn/React-16-8-6-版本存在内存泄露.html</a><span class="copy-path" title="点击复制文章链接"><i class="fa fa-clipboard" data-clipboard-text="http://www.shenzekun.cn/React-16-8-6-版本存在内存泄露.html" aria-label="复制成功!"></i></span></p><p><span>许可协议:</span><i class="fa fa-creative-commons"></i> <a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p></div><script>var clipboard=new Clipboard(".fa-clipboard");$(".fa-clipboard").click(function(){clipboard.on("success",function(){swal({title:"",text:"复制成功",icon:"success",showConfirmButton:!0})})})</script></div><div></div><div><div style="padding:10px 0;margin:20px auto;width:90%;text-align:center"><div>您的支持将鼓励我继续创作!</div><button id="rewardButton" disable="enable" onclick='var qr=document.getElementById("QR");"none"===qr.style.display?qr.style.display="block":qr.style.display="none"'><span>赏</span></button><div id="QR" style="display:none"><div id="wechat" style="display:inline-block"><img id="wechat_qr" src="/image/wechat-reward-image.png" alt="shenzekun WeChat Pay"><p>微信打赏</p></div></div></div></div><footer class="post-footer"><div class="post-tags"><a href="/tags/react/" rel="tag"><i class="fa fa-tag"></i>react</a></div><div class="post-nav"><div class="post-nav-next post-nav-item"><a href="/IVWEB-玩转-WASM-系列-WEBGL-YUV渲染图像实践.html" rel="next" title="IVWEB 玩转 WASM 系列-WEBGL YUV渲染图像实践"><i class="fa fa-chevron-left"></i> IVWEB 玩转 WASM 系列-WEBGL YUV渲染图像实践</a></div><div class="post-nav-prev post-nav-item"></div></div></footer></article><div class="post-spread"></div></div></div><div class="comments" id="comments"><div id="lv-container" data-id="city" data-uid="MTAyMC8yODgyMi81Mzky"></div></div></div><div class="sidebar-toggle"><div class="sidebar-toggle-line-wrap"><span class="sidebar-toggle-line sidebar-toggle-line-first"></span><span class="sidebar-toggle-line sidebar-toggle-line-middle"></span><span class="sidebar-toggle-line sidebar-toggle-line-last"></span></div></div><aside id="sidebar" class="sidebar"><div class="sidebar-inner"><ul class="sidebar-nav motion-element"><li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">文章目录</li><li class="sidebar-nav-overview" data-target="site-overview">站点概览</li></ul><section class="site-overview sidebar-panel"><div class="site-author motion-element" itemprop="author" itemscope itemtype="//schema.org/Person"><img class="site-author-image" itemprop="image" src="https://blog-1257878287.cos.ap-chengdu.myqcloud.com/avatar1.jpg" alt="shenzekun"><p class="site-author-name" itemprop="name">shenzekun</p><p class="site-description motion-element" itemprop="description">Road endless its long and far, I will seek up and down!</p></div><nav class="site-state motion-element"><div class="site-state-item site-state-posts"><a href="/archives"><span class="site-state-item-count">39</span> <span class="site-state-item-name">日志</span></a></div><div class="site-state-item site-state-categories"><a href="/categories"><span class="site-state-item-count">6</span> <span class="site-state-item-name">分类</span></a></div><div class="site-state-item site-state-tags"><a href="/tags"><span class="site-state-item-count">19</span> <span class="site-state-item-name">标签</span></a></div></nav><div class="feed-link motion-element"><a href="/atom.xml" rel="alternate"><i class="fa fa-rss"></i> RSS</a></div><div class="links-of-author motion-element"><span class="links-of-author-item"><a href="https://github.com/shenzekun" target="_blank" rel="external nofollow" title="GitHub"><i class="fa fa-fw fa-github"></i> GitHub</a></span><span class="links-of-author-item"><a href="http://www.jianshu.com/u/b473784d730c" target="_blank" rel="external nofollow" title="简书"><i class="fa fa-fw fa-heartbeat"></i> 简书</a></span><span class="links-of-author-item"><a href="https://twitter.com/shenzekun" target="_blank" rel="external nofollow" title="Twitter"><i class="fa fa-fw fa-twitter"></i> Twitter</a></span><span class="links-of-author-item"><a href="https://segmentfault.com/u/juli_590dd17068b9e" target="_blank" rel="external nofollow" title="SegmentFault"><i class="fa fa-fw fa-meh-o"></i> SegmentFault</a></span><span class="links-of-author-item"><a href="http://blog.csdn.net/qq_33699981?viewmode=list" target="_blank" rel="external nofollow" title="csdn"><i class="fa fa-fw fa-crosshairs"></i> csdn</a></span><span class="links-of-author-item"><a href="https://juejin.im/user/5866ed77ac502e00612f1949" target="_blank" rel="external nofollow" title="掘金"><i class="fa fa-fw fa-spinner"></i> 掘金</a></span></div><div class="links-of-blogroll motion-element links-of-blogroll-inline"><div class="links-of-blogroll-title"><i class="fa fa-fw fa-globe"></i> 推荐阅读</div><ul class="links-of-blogroll-list"><li class="links-of-blogroll-item"><a href="http://www.uisdc.com/" title="优设" target="_blank">优设</a></li><li class="links-of-blogroll-item"><a href="http://www.zhangxinxu.com/" title="张鑫旭" target="_blank">张鑫旭</a></li><li class="links-of-blogroll-item"><a href="http://www.alloyteam.com/nav/" title="Web前端导航" target="_blank">Web前端导航</a></li><li class="links-of-blogroll-item"><a href="http://www.36zhen.com/t?id=3448" title="前端书籍资料" target="_blank">前端书籍资料</a></li><li class="links-of-blogroll-item"><a href="http://ife.baidu.com/" title="百度前端技术学院" target="_blank">百度前端技术学院</a></li><li class="links-of-blogroll-item"><a href="http://wf.uisdc.com/cn/" title="google前端开发基础" target="_blank">google前端开发基础</a></li></ul></div></section><section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active"><div class="post-toc"><div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#分析"><span class="nav-number">1.</span> <span class="nav-text">分析</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#结论"><span class="nav-number">2.</span> <span class="nav-text">结论</span></a></li></ol></div></div></section></div></aside></div></main><footer id="footer" class="footer"><div class="footer-inner"><div class="copyright">© <span itemprop="copyrightYear">2020</span><span class="with-love"><i class="fa fa-heart"></i></span> <span class="author" itemprop="copyrightHolder">shenzekun</span></div><div class="theme-info"><i class="fa fa-pencil"></i> <span class="post-count">博客全站共 40.7k 字</span></div></div></footer><div class="back-to-top"><i class="fa fa-arrow-up"></i></div></div><script type="text/javascript">"[object Function]"!==Object.prototype.toString.call(window.Promise)&&(window.Promise=null)</script><script type="text/javascript" src="/lib/jquery/index.js?v=2.1.3"></script><script type="text/javascript" src="/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script><script type="text/javascript" src="/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script><script type="text/javascript" src="/lib/velocity/velocity.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/velocity/velocity.ui.min.js?v=1.2.1"></script><script type="text/javascript" src="/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script><script type="text/javascript" src="/js/src/utils.js?v=5.0.2"></script><script type="text/javascript" src="/js/src/motion.js?v=5.0.2"></script><script type="text/javascript" src="/js/src/scrollspy.js?v=5.0.2"></script><script type="text/javascript" src="/js/src/post-details.js?v=5.0.2"></script><script type="text/javascript" src="/js/src/bootstrap.js?v=5.0.2"></script><script type="text/javascript">!function(e,t){var n,c=e.getElementsByTagName(t)[0];"function"!=typeof LivereTower&&((n=e.createElement(t)).src="https://cdn-city.livere.com/js/embed.dist.js",n.async=!0,c.parentNode.insertBefore(n,c))}(document,"script")</script><script type="text/javascript">function proceedsearch(){$("body").append('<div class="popoverlay">').css("overflow","hidden"),$(".popup").toggle()}var isfetched=!1,search_path="search.xml";0==search_path.length&&(search_path="search.xml");var path="/"+search_path,searchFunc=function(e,t,a){"use strict";$.ajax({url:e,dataType:"xml",async:!0,success:function(e){isfetched=!0,$(".popup").detach().appendTo(".header-inner");var r=$("entry",e).map(function(){return{title:$("title",this).text(),content:$("content",this).text(),url:$("url",this).text()}}).get(),c=document.getElementById(t),n=document.getElementById(a);c.addEventListener("input",function(){var e=0,t='<ul class="search-result-list">',a=this.value.trim().toLowerCase().split(/[\s\-]+/);n.innerHTML="",this.value.trim().length>1&&r.forEach(function(r){var c=!1,n=r.title.trim().toLowerCase(),s=r.content.trim().replace(/<[^>]+>/g,"").toLowerCase(),o=decodeURIComponent(r.url),i=-1,l=-1,p=-1;if(""!=n&&a.forEach(function(e,t){i=n.indexOf(e),l=s.indexOf(e),(i>=0||l>=0)&&(c=!0,0==t&&(p=l))}),c){e+=1,t+="<li><a href='"+o+"' class='search-result-title'>"+n+"</a>";var h=r.content.trim().replace(/<[^>]+>/g,"");if(p>=0){var u=p-20,d=p+80;u<0&&(u=0),0==u&&(d=50),d>h.length&&(d=h.length);var f=h.substring(u,d);a.forEach(function(e){var t=new RegExp(e,"gi");f=f.replace(t,'<b class="search-keyword">'+e+"</b>")}),t+='<p class="search-result">'+f+"...</p>"}t+="</li>"}}),t+="</ul>",0==e&&(t='<div id="no-result"><i class="fa fa-frown-o fa-5x" /></div>'),""==a&&(t='<div id="no-result"><i class="fa fa-search fa-5x" /></div>'),n.innerHTML=t}),proceedsearch()}})};$(".popup-trigger").click(function(e){e.stopPropagation(),0==isfetched?searchFunc(path,"local-search-input","local-search-result"):proceedsearch()}),$(".popup-btn-close").click(function(e){$(".popup").hide(),$(".popoverlay").remove(),$("body").css("overflow","")}),$(".popup").click(function(e){e.stopPropagation()})</script><script src="https://cdn1.lncld.net/static/js/av-core-mini-0.6.1.js"></script><script>AV.initialize("Cc9hxvKgB63w6aMIIBCV2Bfz-gzGzoHsz","mBmolCuukl1GN11A7m8VQj9f")</script><script>function showTime(e){var t=new AV.Query(e),n=[],o=$(".leancloud_visitors");o.each(function(){n.push($(this).attr("id").trim())}),t.containedIn("url",n),t.find().done(function(e){if(0!==e.length){for(c=0;c<e.length;c++){var t=e[c],i=t.get("url"),s=t.get("time"),l=document.getElementById(i);$(l).find(".leancloud-visitors-count").text(s)}for(var c=0;c<n.length;c++){var i=n[c],l=document.getElementById(i),r=$(l).find(".leancloud-visitors-count");""==r.text()&&r.text(0)}}else o.find(".leancloud-visitors-count").text(0)}).fail(function(e,t){console.log("Error: "+t.code+" "+t.message)})}function addCount(e){var t=$(".leancloud_visitors"),n=t.attr("id").trim(),o=t.attr("data-flag-title").trim(),i=new AV.Query(e);i.equalTo("url",n),i.find({success:function(t){if(t.length>0){var i=t[0];i.fetchWhenSave(!0),i.increment("time"),i.save(null,{success:function(e){$(document.getElementById(n)).find(".leancloud-visitors-count").text(e.get("time"))},error:function(e,t){console.log("Failed to save Visitor num, with error message: "+t.message)}})}else{var s=new e,l=new AV.ACL;l.setPublicReadAccess(!0),l.setPublicWriteAccess(!0),s.setACL(l),s.set("title",o),s.set("url",n),s.set("time",1),s.save(null,{success:function(e){$(document.getElementById(n)).find(".leancloud-visitors-count").text(e.get("time"))},error:function(e,t){console.log("Failed to create")}})}},error:function(e){console.log("Error:"+e.code+" "+e.message)}})}$(function(){var e=AV.Object.extend("Counter");1==$(".leancloud_visitors").length?addCount(e):$(".post-title-link").length>1&&showTime(e)})</script><script>!function(){var t=document.createElement("script"),e=window.location.protocol.split(":")[0];t.src="https"===e?"https://zz.bdstatic.com/linksubmit/push.js":"http://push.zhanzhang.baidu.com/push.js";var s=document.getElementsByTagName("script")[0];s.parentNode.insertBefore(t,s)}()</script></body></html>