JavaScript 总结几个提高性能知识点

前段时间花时间看了大半的《High Performance JavaScript》这本书啊,然后就开始忙项目了,庆幸最忙的一周已经熬过去了。由于空不出时间,这个月写的学习笔记也不多,忙完最苦X的一周,这两天晚上也算是挑灯夜读了...终于是在残血之际将这本书shut down了...

既然读完了,总归是要学到些什么的。说说对这本书的看法先吧,整体的来说,内容还是不错的,就是感觉有点老了(作为前端小白,也可能是自身水平有限,未能体会到其中真意)。看这本书的过程中也是写了挺多代码用以测试的,并且对本书提倡的写法和原先大众的写法的执行分别进行了断点跟踪,对于能实际测出的问题进行理解,当然,下断点跟着执行也看不出的那也没办法咯。对于书中的知识点,这里只是简单的整理出个人所推崇的一部分,当然~ 不喜勿喷。

针对js文件的加载位置

在HTML文件中,<script>标签是可以加在<head>区域和<body>区域的。这里鉴于JavaScript执行和UI渲染的单线程原因,如果js文件载入会阻塞后面对于页面的解析过程,页面会等到js文件完全加载并运行后才继续执行该做的操作。那么问题就来了,这样可能会出现页面空白or卡顿现象。作为一名前端开发,重要的不仅仅止于实现了需求,应该还有优质的用户体验。那么我们就需要消除用户枯燥的等待,针对这个问题,这里有本兽想到的两种解决方案:

1.  如果js文件没有特殊要求指明需要在页面渲染之前载入及编译完成的,那么选择将js文件放到</body>标签前(既所有的页面所呈现内容的后面),css文件还是放到<head>区域(谁也不愿意看一个布局杂乱无章的页面)。这样做就能先让用户看到有布局的页面而不是空白页了,那么也会有人指出:那数据得通过js请求加载进来啊,怎么办呢?可以对数据的加载做排序,急需呈现的接口放前面执行,不是那么需要的可以延后执行,同时做个简单的载入动画or提示。

2.  如果这些js文件有指明需要先执行了,才能更好的展示页面内容,那么就在第一个js或者页面上先放个载入小动画,可以一些有趣的或者萌萌的动画场景。这样也是能较好的避免用户等待的无聊,说不定人家还对这个载入动画更感兴趣呢,这样可提升项目的用户体验感。

最终推荐:将<script>标签尽可能的放到</body>标签前面加载,以提升用户体验。

针对js文件的合并
在很多团队开发中,我们可能会将不同功能的代码块分别放置在不同的js文件中,以便于开发过程中众人合作写代码会更加方便,毕竟只需要找对应文件夹或文件而不是在一个很长的文件中找一个方法。这确实是会提高团队开发效率及新人加入后的更容易进行二次开发及维护。那么将这个问题放到页面性能里呢?这正是问题所在,在这本书中指出:Each HTTP request brings with it additional performance overhead,so downloading one single 100 KB file will be faster than downloading four 25 KB files.

下载1个100KB的文件比下载4个25KB的文件要快,而开发过程中区分开各个文件又有很大的好处,那么合并这个问题也就放在开发完后再处理咯,相信这个操作大家都不会陌生吧,现在的前端工具这么丰富,各位习惯用什么压缩就用什么压缩吧~
这里简单提出下,在载入文件方面还可以用到defer和async属性,用于延迟加载和异步加载,在现代浏览器中,大多数是已经支持defer属性了,还没习惯用这个额,也不知道具体会不会存在什么问题。有兴趣的朋友可自行google该知识点,这里件简单提下吧。

现在的框架也大多配合懒加载和按需加载了。

更快速的数据访问

对于浏览器来说,一个标识符所处的位置越深,去读写他的速度也就越慢(对于这点,原型链亦是如此)。这个应该不难理解,简单比喻就是:杂货店离你家越远,你去打酱油所花的时间就越长... 熊孩子,打个酱油那么久,菜早烧焦了 -.-~

如果我们需要在当前函数内多次用到一个变量值,那么我们可以用一个局部变量先将其存储起来,案例如下:

  //修改前
  function showLi(){
      var i = 0;
      for(;i<document.getElementsByTagName("li").length;i++){    //一次访问document
          console.log(i,document.getElementsByTagName("li")[i]);  //三次访问document
      };
  };
  //修改后
  function showLi(){
      var li_s = document.getElementsByTagName("li");  //一次访问document
      var i = 0;
      for(;i<li_s.length;i++){
          console.log(i,li_s[i]);  //三次访问局部变量li_s
      };
  };

DOM操作的优化

众所周知的,DOM操作远比javascript的执行耗性能,虽然我们避免不了对DOM进行操作,但我们可以尽量去减少该操作对性能的消耗。

让我们通过代码解释这个问题:

  function innerLi_s(){
      var i = 0;
      for(;i<20;i++){
          document.getElementById("Num").innerHTML="A"; //进行了20次循环,每次又有2次DOM元素访问:一次读取innerHTML的值,一次写入值
      };
  };

针对以上方法进行一次改写:

  function innerLi_s(){
      var content ="";
      var i = 0;
      for(;i<20;i++){
          content += "A";  //这里只对js的变量循环了20次
      };
      document.getElementById("Num").innerHTML += content;  //这里值进行了一次DOM操作,又分2次DOM访问:一次读取innerHTML的值,一次写入值
  };

减少Dom的重绘重排版

元素布局的改变或内容的增删改或者浏览器窗口尺寸改变都将会导致重排,而字体颜色或者背景色的修改则将导致重绘。
对于类似以下代码的操作,据说现代浏览器大多进行了优化(将其优化成1次重排版):

  //修改前
  var el = document.getElementById("div");
  el.style.borderLeft = "1px"; //1次重排版
  el.style.borderRight = "2px"; //又1次重排版
  el.style.padding = "5px"; //还有1次重排版
  //修改后
  var el = document.getElementById("div");
  el.style.cssText = "border-left:1px;border-right:2px;padding:5px"; //1次重排版

针对多重操作,以下三种方法也可以减少重排版和重绘的次数:

1.Dom先隐藏,操作后再显示 2次重排 (临时的display:none)

2.document.createDocumentFragment() 创建文档片段处理,操作后追加到页面 1次重排

3.var newDOM = oldDOM.cloneNode(true)创建Dom副本,修改副本后oldDOM.parentNode.replaceChild(newDOM,oldDOM)覆盖原DOM 2次重排

循环的优化

这应该是较多人都知道的写法了,简单带过即可(后面还是用代码+注释形式说明)~

  //修改前
  var i = 0;
  for(;i<arr.lengthli++){  //每次循环都需要获取数组arr的length
      console.log(arr[i]);
  }
  //修改后
  var i = 0;
  var len = arr.length;  //获取一次数组arr的length
  for(;i<len;i++){
      console.log(arr[i]);
  }
  //or
  var i = arr.length;;
  for(;i;i--){
      console.log(arr[i]);
  }

合理利用二进制

如:对2取模,则偶数最低位是0,奇数最低位是0,与1进行位与操作的结果是0,奇数的最低位是1,与1进行位与操作的结果是1。

代码如下:

  .odd{color:red}
  .even{color:yellow}
    <ul>
        <li>1</li>
        <li>2</li>
        <li>3</li>
        <li>4</li>
        <li>5</li>
        <li>6</li>
    </ul>
  var i = 0;
  var lis = document.getElementsByTagName("li");
  var len = lis.length;
  for(;i<len;i++){
      if(i&1){
          lis[i].className = "even";
      } else{
          lis[i].className = "odd";
      }
  };

虽说现代浏览器都已经做的很好了,但是本兽觉得这是自己对代码质量的一个追求。并且可能一个点或者两个点不注意是不会产生多大性能影响,但是从多个点进行优化后,可能产生的就会质的飞跃了~

时间: 2024-10-08 06:46:02

JavaScript 总结几个提高性能知识点的相关文章

Javascript函数式编程要掌握的知识点讲解

一:理解call和apply 及arguments.callee ECMAScript3给Function的原型定义了两个方法,他们是Function.prototype.call 和 Function.prototype.apply. 其实他们的作用是一样的,只是传递的参数不一样而已: 1. apply; 接受2个参数,第一个参数指定了函数体内this对象的指向,第二个参数为一个类似数组的集合,比如如下代码: var yunxi = function(a,b){ console.log([a,

提高性能:用RequireJS优化Wijmo Web页面

上周Wijmo 2014 V2版本刚刚发布(下载地址),  有网友下载后发现仅仅使用了40个Widgets的一小部分,还需要加载全部的jquery.wijmo-pro.all.3.20142.45.min.js包? 即对仅使用部分的Widget,有无办法优化而提高网络性能呢. 答案是肯定的,有办法. 其中针对这种情况,使用Require.JS再合适不过了,实际上Wijmo 2013年已经开始支持Require.JS了,如下是Wijmo支持的JavaScript类库的全图. 本文就通过对比的方式说

Phalcon之 提高性能:下一步该做什么?(Increasing Performance: What’s next?)

要开发出高性能的应用程序需要考虑多方面的因素: 服务器, 客户端, 网络, 数据库, web服务器,静态资源等. 本章中我集中分析如何提升系统的性能及如何检测应用的瓶颈. 关于服务端(Profile on the Server)? 每种应用都有不同, 持久的性能分析对找出系统瓶颈是非常必要的. 性能分析可以让我们更直观的看出何处为性能瓶颈,何处不是. 性能分析在一个请求中和另一请求中可能表现不一,所以要做出足够的分析及权衡方可给出结论. 关于 XDebug(Profiling with XDeb

拆分初始化负载,提高性能

拆分初始化负载,提高性能 1  在初始化时加载必要的javaScript,其余的JavaScript稍后再加载:避免给用户带来响应停顿的印象.(在初始化页面时,很多函数下载了,但并未执行): 2   寻找拆分的函数 Firebug的JavaScript性能分析器能显示出在触发onload事件之前执行的函数名.我们可以通过这个列表,把js代码拆分成一个页面初始化需要加载的文件:另一个可以延迟加载.(需要保留醋无处理以及条件判断的代码) Doloto可以自动拆分javascript代码的系统,可以拆

SQL中使用WITH AS提高性能,使用公用表表达式(CTE)简化嵌套SQL

一.WITH AS的含义     WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会被整个SQL语句所用到.有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数据的部分. 特别对于UNION ALL比较有用.因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,所以可以使用WITH AS短语,则只要执行一遍即可.如果WITH AS短语所定

MSSQL - SqlDataAdapter连接数据库提高性能用法

SqlDataAdapter 与 SqlConnection 和 SqlCommand 一起使用,以便在连接到 SQL Server 数据库时提高性能. SqlDataAdapter 的这一实现自动打开和关闭 SqlConnection(如果它尚未打开). 在必须为两个或更多 SqlDataAdapter 对象调用 Fill 方法的应用程序中,它会非常有用. 如果SqlConnection 已打开,则必须显式调用 Close 或 Dispose 以将其关闭. private static Dat

Java编程提高性能时需注意的地方

最近的机器内存又爆满了,除了新增机器内存外,还应该好好review一下我们的代码,有很多代码编写过于随意化,这些不好的习惯或对程序语言的不了解是应该好好打压打压了. 下面是参考网络资源和总结一些在java编程中尽可能做到的一些地方 1.尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间,提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面 第一,控制资源的使用,通过线程同步来控制资源的并发访问 第二,控制实例的产生,以达到节约资源的目的 第三,控制

使用C# yield关键字来提高性能和可读性

对于”yield”这个关键字我已经见过N次了,直到最近我才知道这个关键字所蕴含的力量.我将在下面展示出一些使用”yield”让你的代码有更高可读性和更好性能的例子. 为了让你对yield有一些快速概览,我首先要展示一个没有使用这个关键字的例子,下面的代码很简单,但在我最近的项目中却很常见 IList<string> FindBobs(IEnumerable<string> names) { var bobs = new List<string>(); foreach(v

EF提高性能

实体框架 5 性能注意事项 作者:David Obando.Eric Dettinger 等 发布时间:2012 年 4 月 1.简介 对象关系映射框架是一种在面向对象的应用程序中提供数据访问抽象的便捷方式.对于 .NET 应用程序,Microsoft 推荐的 O/RM 是实体框架.但任何抽象都要考虑性能. 本白皮书旨在介绍在使用实体框架开发应用程序时的性能注意事项,使开发人员了解能够影响性能的实体框架内部算法,以及提供有关进行调查及在使用实体框架的应用程序中提高性能的提示.网络上有大量很好的有