编写高性能&#106avascript

2023-08-21    分类: 网站建设

百度权重查询 站长交易 友情链接交换 网站监控 服务器监控 seo监控

许多&#106avascript引擎,如Google的V8引擎(被Chrome和Node所用),是专门为需要快速执行的大型&#106avascript应用所设计的。假如你是一个开发者,并且关心内存使用情况与页面性能,你应该了解用户浏览器中的&#106avascript引擎是如何运作的。无论是V8,SpiderMonkey的(Firefox)的Carakan(Opera),Chakra(IE)或其他引擎,这样做可以帮助你更好地优化你的应用程序。这并不是说应该专门为某一浏览器或引擎做优化,万万别这么做。</p><p>但是,你应该问自己几个问题:</p><p>&bull;在我的代码里,是否可以使代码更高效一些</p><p>&bull;主流的&#106avascript引擎都做了哪些优化</p><p>&bull;什么是引擎无法优化的,垃圾回收器(GC)是否能回收我所期望的东西</p><p>加载快速的网站就像是一辆快速的跑车,需要用到特殊定制的零件</p><p>编写高性能代码时有一些常见的陷阱,在这篇文章中,我们将展示一些经过验证的、更好的编写代码体例。</p><p><strong>那么,&#106avascript在V8里是如何工作的?</strong></p><p>假如你对JS引擎没有较深的了解,开发一个大型Web应用也没啥问题,就好比会开车的人也只是看过引擎盖而没有看过车盖内的引擎一样。鉴于Chrome是我的浏览器,所以谈一下它的&#106avascript引擎。V8是由以下几个核心部分组成:</p><p>&bull;一个基本的编译器,它会在代码执行前解析&#106avascript代码并生成本地机器码,而不是执行字节码或简单地诠释它。这些代码好开始并不是高度优化的。</p><p>&bull;V8将对象构建为对象模型。在&#106avascript中对象体现为关联数组,但是在V8中对象被看作是隐藏的类,一个为了优化查询的内部类型系统。</p><p>&bull;运行时分析器监视正在运行的系统,并标识了&ldquo;hot&rdquo;的函数(例如花费很长时间运行的代码)。</p><p>&bull;优化编译重视新编译和优化那些被运行时分析器标识为&ldquo;hot&rdquo;的代码,并进行&ldquo;内联&rdquo;等优化(例如用被调用者的主体替代函数调用的位置)。</p><p>&bull;V8支撑去优化,这意味着优化编译器假如发现对于代码优化的假设过于乐观,它会舍弃优化过的代码。</p><p>&bull;V8有个垃圾收集器,了解它是如何工作的和优化&#106avascript一样主要。</p><p><strong>垃圾回收</strong></p><p>垃圾回收是内存管理的一种形式,其实就是一个收集器的概念,尝试回收不再被使用的对象所占用的内存。在&#106avascript这种垃圾回收语言中,应用程序中仍在被引用的对象不会被消灭。</p><p>手动消弭对象引用在大多数情况下是没有需要的。通过简单地把变量放在需要它们的地方(理想情况下,尽可能是局部作用域,即它们被使用的函数里而不是函数外层),一切将运作地很好。</p><p>垃圾回收器尝试回收内存</p><p>在&#106avascript中,是不可能强制进行垃圾回收的。你不应该这么做,因为垃圾收集过程是由运行时控制的,它知道什么是好好的清理时机。</p><p><strong>&ldquo;消弭引用&rdquo;的误解</strong></p><p>网上有许多关于&#106avascript内存回收的讨论都谈到delete这个关键字,虽然它可以被用来删除对象(map)中的属性(key),但有部分开发者认为它可以用来强制&ldquo;消弭引用&rdquo;。建议尽可能避免使用delete,在下面的例子中delete o.x 的弊大于利,因为它改变了o的隐藏类,并使它成为一个"慢对象"。</p><blockquote><p>var o = { x:1 };</p><p>delete o.x; // true</p><p>o.x; // undefined</p></blockquote> <p>你会很容易地在流行的JS库中找到引用删除&mdash;&mdash;这是具有语言目的性的。这里需要注重的是避免在运行时修改&rdquo;hot&rdquo;对象的结构。&#106avascript引擎可以检测出这种&ldquo;hot&rdquo;的对象,并尝试对其进行优化。假如对象在生命周期中其结构没有较大的改变,引擎将会更容易优化对象,而delete操作现实上会触发这种较大的结构改变,因此不利于引擎的优化。</p><p>对于null是如何工作也是有误解的。将一个对象引用设置为null,并没有使对象变&ldquo;空&rdquo;,只是将它的引用设置为空而已。使用o.x= null比使用delete会更好些,但可能也不是很需要。</p><blockquote><p>var o = { x:1 };</p><p>o = null;</p><p>o; // null</p><p>o.x // TypeError</p></blockquote> <p>假如此引用是当前对象的好后引用,那么该对象将被作为垃圾回收。假如此引用不是当前对象的好后引用,则该对象是可访问的且不会被垃圾回收。</p><p>另外需要注重的是,全局变量在页面的生命周期里是不被垃圾回收器清理的。无论页面打开多久,&#106avascript运行时全局对象作用域中的变量会一向存在。</p><blockquote><p>var myGlobalNamespace = {};</p></blockquote> <p>全局对象只会在刷新页面、导航到其他页面、关闭标签页或退出浏览器时才会被清理。函数作用域的变量将在超出作用域时被清理,即退出函数时,已经没有任何引用,这样的变量就被清理了。</p><p><strong>经验法则</strong></p><p>为了使垃圾回收器尽早收集尽可能多的对象,不要hold着不再使用的对象。这里有几件事需要记住:</p><p>&bull;正如前面提到的,在合适的范围内使用变量是手动消弭引用的更好选择。即一个变量只在一个函数作用域中使用,就不要在全局作用域声明它。这意味着更干净省心的代码。</p><p>&bull;确保解绑那些不再需要的事件监听器,尤其是那些即将被销毁的DOM对象所绑定的事件监听器。</p><p>&bull;假如使用的数据缓存在本地,确保清理一下缓存或使用老化机制,以避免大量不被重用的数据被存储。</p><p><strong>函数</strong></p><p>接下来,我们谈谈函数。正如我们已经说过,垃圾收集的工作原理,是通过回收不再是访问的内存块(对象)。为了更好地说明这一点,这里有一些例子。</p><blockquote><p>function foo(){</p><p>var bar = new LargeObject();</p><p>bar.someCall();</p><p>}</p></blockquote> <p>当foo返回时,bar指向的对象将会被垃圾收集器主动回收,因为它已没有任何存在的引用了。</p><p>对比一下:</p><blockquote><p>function foo(){</p><p>var bar = new LargeObject();</p><p>bar.someCall();</p><p>return bar;</p><p>}</p><p>// somewhere else</p><p>var b = foo();</p></blockquote> <p>现在我们有一个引用指向bar对象,这样bar对象的生存周期就从foo的调用一向持续到调用者指定别的变量b(或b超出范围)。</p><p><strong>闭包(CLOSURES)</strong></p><p>当你看到一个函数,返回一个内部函数,该内部函数将获得范围外的访问权,即使在外部函数执行之后。这是一个基本的闭包&nbsp;&mdash;&mdash; 可以在特定的上下文中设置的变量的表达式。例如:</p><blockquote><p>function sum (x){</p><p>function sumIt(y){</p><p>return x + y;</p><p>};</p><p>return sumIt;</p><p>}</p><p>// Usage</p><p>var sumA = sum(4);</p><p>var sumB = sumA(3);</p><p>console.log(sumB); // Returns 7</p></blockquote> <p>在sum调用上下文中生成的函数对象(sumIt)是无法被回收的,它被全局变量(sumA)所引用,并且可以通过sumA(n)调用。</p><p>让我们来看看另外一个例子,这里我们可以访问变量largeStr吗?</p><blockquote><p>var a = function (){</p><p>var largeStr = new Array(1000000).join(&lsquo;x&rsquo;);</p><p>return function (){</p><p>return largeStr;</p><p>};</p><p>}();</p></blockquote> <p>是的,我们可以通过a()访问largeStr,所以它没有被回收。下面这个呢?</p><blockquote><p>var a = function (){</p><p>var smallStr = &lsquo;x&rsquo;;</p><p>var largeStr = new Array(1000000).join(&lsquo;x&rsquo;);</p><p>return function (n){</p><p>return smallStr;</p><p>};</p><p>}();</p></blockquote> <p>我们不能再访问largeStr了,它已经是垃圾回收候选人了。【译者注:因为largeStr已不存在外部引用了】</p><p><strong>准时器</strong></p><p>好糟的内存泄露地方之一是在循环中,或者在setTimeout()/ setInterval()中,但这是相当常见的。思考下面的例子:</p><blockquote><p>var myObj = {</p><p>callMeMaybe:function (){</p><p>var myRef = this;</p><p>var val = setTimeout(function (){</p><p>console.log(&lsquo;Time is running out!&rsquo;);</p><p>myRef.callMeMaybe();</p><p>},1000);</p><p>}</p><p>};</p></blockquote> <p>假如我们运行myObj.callMeMaybe();来启动准时器,可以看到控制台每秒打印出&ldquo;Time is running out!&rdquo;。假如接着运行myObj =&nbsp;null,准时器依旧处于激活状况。为了能够持续执行,闭包将myObj传递给setTimeout,这样myObj是无法被回收的。相反,它引用到myObj的因为它捕捉了myRef。这跟我们为了保持引用将闭包传给其他的函数是一样的。</p><p>同样值得牢记的是,setTimeout/setInterval调用(如函数)中的引用,将需要执行和完成,才可以被垃圾收集。</p><p><strong>当心性能陷阱</strong></p><p>永远不要优化代码,直到你真正需要。现在经常可以看到一些基准测试,显示N比M在V8中更为优化,但是在模块代码或应用中测试一下会发现,这些优化真正的效果比你期望的要小的多。</p><p>做的过多还不如什么都不做.</p><p>比如我们想要创建这样一个模块:</p><p>&bull;需要一个本地的数据源包含数字ID</p><p>&bull;绘制包含这些数据的表格</p><p>&bull;添加事件处理程序,当用户点击的任何单元格时切换单元格的css class</p><p>这个问题有几个不同的因素,虽然也很容易解决。我们如何存储数据,如何高效地绘制表格并且append到DOM中,如何更优地处理表格事件?</p><p>面对这些问题好开始(无邪)的做法是使用对象存储数据并放入数组中,使用jQuery遍历数据绘制表格并append到DOM中,好后使用事件绑定我们期望地点击行为。</p><p>注重:这不是你应该做的</p><blockquote><p>var moduleA = function (){</p><p>return {</p><p>data:dataArrayObject,</p><p>init:function (){</p><p>this.addTable();</p><p>this.addEvents();</p><p>},</p><p>addTable:function (){</p><p>for (var i = 0; i &lt;rows; i++){</p><p>$tr = $(&lsquo;&lt;tr&gt;&lt;/tr&gt;&rsquo;);</p><p>for (var j = 0; j &lt;this.data.length; j++){</p><p>$tr.append(&lsquo;&lt;td&gt;&rsquo; + this.data[j][&lsquo;id&rsquo;]+ &lsquo;&lt;/td&gt;&rsquo;);</p><p>}</p><p>$tr.appendTo($tbody);</p><p>}</p><p>},</p><p>addEvents:function (){</p><p>$(&lsquo;table td&rsquo;).on(&lsquo;click&rsquo;,function (){</p><p>$(this).toggleClass(&lsquo;active&rsquo;);</p><p>});</p><p>}</p><p>};</p><p>}();</p></blockquote> <p>这段代码简单有用地完成了义务。</p><p>但在这种情况下,我们遍历的数据只是本应该简单地存放在数组中的数字型属性ID。有趣的是,直接使用DocumentFragment和本地DOM方法比使用jQuery(以这种体例)来生成表格是更优的选择,当然,事件代理比单独绑定每个td具有更高的性能。</p><p>要注重虽然jQuery在内部使用DocumentFragment,但是在我们的例子中,代码在循环内调用append并且这些调用涉及到一些其他的小知识,因此在这里起到的优化作用不大。希望这不会是一个痛点,但请务必进行基准测试,以确保自己代码ok。</p><p>对于我们的例子,上述的做法带来了(期望的)性能提拔。事件代理对简单的绑定是一种改进,可选的DocumentFragment也起到了助推作用。</p><blockquote><p>var moduleD = function (){</p><p>return {</p><p>data:dataArray,</p><p>init:function (){</p><p>this.addTable();</p><p>this.addEvents();</p><p>},</p><p>addTable:function (){</p><p>var td,tr;</p><p>var frag = document.createDocumentFragment();</p><p>var frag2 = document.createDocumentFragment();</p><p>for (var i = 0; i &lt;rows; i++){</p><p>tr = document.createElement(&lsquo;tr&rsquo;);</p><p>for (var j = 0; j &lt;this.data.length; j++){</p><p>td = document.createElement(&lsquo;td&rsquo;);</p><p>td.appendChild(document.createTextNode(this.data[j]));</p><p>frag2.appendChild(td);</p><p>}</p><p>tr.appendChild(frag2);</p><p>frag.appendChild(tr);</p><p>}</p><p>tbody.appendChild(frag);</p><p>},</p><p>addEvents:function (){</p><p>$(&lsquo;table&rsquo;).on(&lsquo;click&rsquo;,&lsquo;td&rsquo;,function (){</p><p>$(this).toggleClass(&lsquo;active&rsquo;);</p><p>});</p><p>}</p><p>};</p><p>}();</p> <p> 网站标题:<a href="/news34/277584.html">编写高性能&#106avascript</a> <br> 路径分享:<a href="/news34/277584.html">/news34/277584.html</a> </p> <p> <a href="/" target="_blank">成都网站建设公司</a>_<a href="https://www.cdcxhl.cn/" target="_blank">创新互联</a>,为您提供<a href="/news/wxgzh/">微信公众号</a>、<a href="/news/waimaojianzhan/">外贸建站</a>、<a href="/news/pinpaijianshe/">品牌网站建设</a>、<a href="/news/mobile/">手机网站建设</a>、<a href="/news/yidongjianshe/">移动网站建设</a>、<a href="/news/appkaifa/">App开发</a> </p> <p class="adpic"> <a href="/service/ad.html" target="_blank" class="ad">广告</a> <a href="" target="_blank" class="adimg"><img src=""></a> </p> <p class="copy"> 声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: <a href="/" target="_blank">创新互联</a> </p> </div> <div class="newsmorelb"> <p>猜你还喜欢下面的内容</p> <ul> <li> <a href="/news32/277582.html">辽阳网站排名优化:如何充分发挥SEO功能</a> <span>2023-08-21</span> </li><li> <a href="/news30/277580.html">徐汇企业为什么离不开网页设计</a> <span>2023-08-21</span> </li><li> <a href="/news28/277578.html">天津网站建设_提供手机网站设计制作_高端建站公司</a> <span>2023-08-21</span> </li><li> <a href="/news26/277576.html">网站建设为什么要使用DIV+CSS设计网站</a> <span>2023-08-21</span> </li><li> <a href="/news24/277574.html">为什么企业应该建设自适应网站</a> <span>2023-08-21</span> </li><li> <a href="/news22/277572.html">网站设计发展新趋势</a> <span>2023-08-21</span> </li><li> <a href="/news20/277570.html">江西网站优化公司如何制定客户seo方案</a> <span>2023-08-21</span> </li> </ul> </div> </div> <div class="col-lg-3 noneb"> <a href="/h5.html" title="h5响应式网站建设" target="_blank"><img src="/upload/news/zishiyingwangzhan.png" alt="h5响应式网站建设" class="img-responsive"></a> <div class="bkright"> <p><a href="/news/jianshe/">网站建设知识</a></p> <ul> <li> <a class="text_overflow" href="/news33/277583.html">长治网站设计,让您的企业在互联网上脱颖而出!</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news31/277581.html">网站建设上线后必须要做的三件事</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news29/277579.html">澳门网页设计常见流程</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news27/277577.html">延庆SEO优化的文章怎么写?</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news25/277575.html">蓟州网站建设上线后要如何进行维护</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news23/277573.html">百度优化:关键词突然搜索不到的原因分析?</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news21/277571.html">定制网站:网站需要具备哪些基础功能</a> <span>2023-08-21</span> </li> <li> <a class="text_overflow" href="/news19/277569.html">小型冷门企业需要做营销型网站吗?</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news18/277568.html">北京网站优化:搜索引擎如何排名一个页面?</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news17/277567.html">哪种网站优化公司做排名效果好?</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news16/277566.html">这样的网站设计方案更吸引用户</a> <span>2023-08-21</span> </li><li> <a class="text_overflow" href="/news15/277565.html">网页设计:商城类网站设计需要有这些</a> <span>2023-08-21</span> </li> </ul> </div> <div class="bkright tag"> <p><a href="/hangye/" target="_blank">行业网站建设</a></p> <ul> <li class="col-lg-6 col-md-6 col-sm-6 col-xs-6"> <a href="/hangye/suliaodai/" target="_blank">塑料袋</a> </li><li class="col-lg-6 col-md-6 col-sm-6 col-xs-6"> <a href="/hangye/lajitong/" target="_blank">垃圾桶</a> </li><li class="col-lg-6 col-md-6 col-sm-6 col-xs-6"> <a href="/hangye/bdfhw/" target="_blank">被动防护网</a> </li><li class="col-lg-6 col-md-6 col-sm-6 col-xs-6"> <a href="/hangye/ggsj/" target="_blank">广告设计</a> </li><li class="col-lg-6 col-md-6 col-sm-6 col-xs-6"> <a href="/hangye/weixiufdj/" target="_blank">发电机维修</a> </li><li class="col-lg-6 col-md-6 col-sm-6 col-xs-6"> <a href="/hangye/zsljbc/" target="_blank">自上料搅拌车</a> </li><li class="col-lg-6 col-md-6 col-sm-6 col-xs-6"> <a href="/hangye/hgdsj/" target="_blank">火锅店设计</a> </li><li class="col-lg-6 col-md-6 col-sm-6 col-xs-6"> <a href="/hangye/muwu/" target="_blank">木屋</a> </li> </ul> </div> </div> </div> <footer> <div class="carousel-inner footjz"> <div class="container"> <i class="icon iconfont zbw"></i> 高品质定制 <i class="icon iconfont"></i> 跨终端自动兼容 <i class="icon iconfont"></i> 节约开发成本 <i class="icon iconfont"></i> 开发周期短 <i class="icon iconfont"></i> 一体化服务 <button type="button" class="btn btn-default btn-lg" onClick="window.location.href='tencent://message/?uin=631063699&Site=&Menu=yes'"> 立即开始2800定制网站建设</button> <button type="button" class="btn btn-default btn-xs" onClick="window.location.href='tencent://message/?uin=631063699&Site=&Menu=yes'"> 2800定制网站建设</button> </div> </div> <div class="carousel-inner bqsy"> <div class="container"> <div class="lxfs"> <h4 class="yutelnone">028-86922220 13518219792</h4> <h4 class="yutelblock"><a href="tel:02886922220">028-86922220</a> <a href="tel:13518219792">13518219792</a></h4> <a class="btn btn-default" href="tencent://message/?uin=532337155&Site=&Menu=yes" role="button">网站建设<span>QQ</span>:532337155</a> <a class="btn btn-default" href="tencent://message/?uin=631063699&Site=&Menu=yes" role="button">营销推广<span>QQ</span>:631063699</a> <a class="btn btn1 btn-default" href="mqqwpa://im/chat?chat_type=wpa&uin=532337155&version=1&src_type=web&web_src=oicqzone.com" role="button">网站制作<span>QQ</span>:532337155</a> <a class="btn btn1 btn-default" href="mqqwpa://im/chat?chat_type=wpa&uin=631063699&version=1&src_type=web&web_src=oicqzone.com" role="button">营销推广<span>QQ</span>:631063699</a> <a class="btn btn-default nonea" href="tencent://message/?uin=1683211881&Site=&Menu=yes" role="button">售后QQ:1683211881</a> <div class="dz">专注: <a href="http://www.cdkjz.cn/" target="_blank">网站设计制作</a><a href="https://www.cdxwcx.com/" target="_blank">做网站</a><a href="https://www.xwcx.net/" target="_blank">服务器托管</a><a href="http://www.cxhlcq.com/" target="_blank">重庆网站建设公司</a><a href="http://www.cxhlcq.com/" target="_blank">重庆网站制作</a> <address>地址:成都太升南路288号锦天国际A幢10楼</address> </div> </div> <div class="bzdh dz"><img src="../imges/bottom_logo.png" alt="创新互联"> <p><a href="/menu.html" target="_blank">成都创新互联科技有限公司</a><br> Tel:400-028-6601(7x24h)</p></div> </div> </div> </footer> <div class='link'> <a href='http://www.verzuimpartners.com'>2024欧洲杯竞猜官网</a> | <a href='http://www.its-our-pleasure.com'>BET体育官方网站(中国)有限公司</a> | <a href='http://www.vspflooring.com'>星空体育·(StarSky Sports)</a> | <a href='http://www.zeusalarm.com'>bet官方(中国)有限公司</a> | <a href='http://www.dragongardentogo.com'>在线体育竞猜(中国)有限公司</a> | <a href='http://www.terranuragica.com'>BET体育|中国有限公司</a> | <a href='http://www.haygg.com'>bat365在线平台·(中国)官方网站</a> | <a href='http://www.jebsenwineestates.com'>半岛·体育(中国)官方网站</a> | </div> </body> </html>