stb前端开发js性能优化总结

js性能优化

javascript是一种解释型语言,性能无法达到和C、C++等编译语言的水平,但还是有一些方法来改进。

1、循环

    JavaScript中的循环方式有for(;;)、while()、for(in)3种。

当中for(in)的效率极差,由于for(in)运行过程中须要查询散列键。for(;;)和while()比較。while循环的效率要优于for(;;)。

 

2、局部变量和全局变量

 

        局部变量的訪问速度更快,由于全局变量事实上是全局对象的成员。而局部变量是放在函数的堆栈其中的。

 

3、不使用eval

 

       使用eval函数相当于在执行时再次调用解释引擎对内容进行解释执行

 

4、降低对象查找

 

     由于JavaScript的特性,对于类是表达式a.b.c.d.e,须要至少4次查询操作。首先检查a在检查a中的b,如此往下。

应尽量避免出现这种表达式、能够利用局部变量把要訪问的终于结果放入一个暂时的位置进行查询。

 

     这一点能够和循环结合起来。比如对一个数组能够先取他的长度 var len = a.length

 

     ##事实上java 中对于列表的循环也是先取size给一个暂时变量

 

5、字符串连接

 

     假设是追加字符串,最好使用s+=anotherStr操作。而不要使用s=s+""

 

     可是假设要连接多个字符串,应该少用+= 比如:

java 代码

s+=a;      

s+=b;   

s+=c;   

     应该写成 s+=a+b+c;

 

     假设是收集字符串,比方收集字符串。最好使用一个缓存实现。详细的实现思路就是使用Javascript数组来收集每一个字符串,最好使用join方法将这些字符串连接起来。如以下代码所看到的:

 

 

var buf = new Array();   

for(var i=0;i<100;i++){   

   buf.push(i.toString());   

}   

var all = buf.join("");  

6、类型转换

 

    类型转换是JavaScript编程中easy出错的地方,由于JavaScript是动态类型语言,即弱类型语言,不能指定变量的详细类型。

 

    1、把数字转换成字符串,应用""+1,尽管比較别扭一点、但效率是最高的

 

          (""+)>String()>.toString()>newString()

 

   String()属于内部函数,所以速度非常快,toString()要查询原型中的函数,new String()用于返回一个精确的副本。

 

    2、浮点数转换成整型 parseInt()用于将字符串转换成数字,应该使用Math.floor()或者Math.round()来实现浮点型和整型之间的转换。

 

    3、对于自己定义的对象,假设定义了toString()方法进行类型转换的话,推荐显示调用toString()

 

7、使用直接量

 

     以往我们都使用new Array(parm,parm1..)等形式,对于直接量的解释JavaScript支持使用[param,param1....]来直接表达一个数组。

 

     前一种方式调用Array内部构造器。而后一种方式是解释引擎直接解释的,故运行速度要稍微快一点。同理var foo = {}比 var foo = new Object()快。var reg=/..../比 var reg=new RegExp()运行的快些。

8、字符串遍历

 

     优先使用正則表達式

 

9、高级对象

 

     自己定义高级对象和Date、RegExp等对象构造时会消耗大量的时间和资源

 

10、插入HTML

 

     document.write效率较低。innerHTML效率较高

 

11、下标查询

 

      使用直接的下标查找一个对象的属性比通过.name方法要快非常多

 

12、创建DOM节点

 

      通常我们可能会使用字符串直接写HTML语句来创建节点。实际上这样有例如以下缺点:

 

     1、无法保证代码的有效性;

 

     2、字符串操作效率低。

 

   应该使用documeng.createElement()方法。假设存在现成的样板节点,应该使用cloneNode()方法。

 

所以第一原则就是仅仅须要为IE6(未打补丁的JScript 5.6或更早版本号)做优化。

 

假设你的程序已经优化到在IE6下能够接受的性能。那基本上在其它浏览器上性能就全然没有问题。

 

因此。注意我以下讲的很多问题在其它引擎上可能全然不同,比如在循环中进行字符串拼接,通常觉得须要用Array.join的方式,可是因为SpiderMonkey等引擎对字符串的“+”运算做了优化,结果使用Array.join的效率反而不如直接用“+”!

可是假设考虑IE6,则其它浏览器上的这样的效率的区别根本不值一提。

 

JS优化与其它语言的优化也仍然有同样之处。

比方说。不要一上来就急吼吼的做优化,那样毫无意义。优化的关键,仍然是要把精力放在最关键的地方。也就是瓶颈上。一般来说。瓶颈总是出如今大规模循环的地方。

这倒不是说循环本身有性能问题,而是循环会迅速放大可能存在的性能问题。

 

所以第二原则就是以大规模循环体为最主要优化对象。

 

下面的优化原则,仅仅在大规模循环中才有意义。在循环体之外做此类优化基本上是没有意义的。

 

眼下绝大多数JS引擎都是解释运行的。而解释运行的情况下,在全部操作中,函数调用的效率是较低的。此外,过深的prototype继承链或者多级引用也会减少效率。

JScript中。10级引用的开销大体是一次空函数调用开销的1/2。

这两者的开销都远远大于简单操作(如四则运算)。

 

所以第三原则就是尽量避免过多的引用层级和不必要的多次方法调用。

 

特别要注意的是,有些情况下看似是属性訪问。实际上是方法调用。比如全部DOM的属性。实际上都是方法。在遍历一个NodeList的时候,循环条件对于nodes.length的訪问,看似属性读取,实际上是等价于函数调用的。

并且IE DOM的实现上,childNodes.length每次是要通过内部遍历又一次计数的。(My god,可是这是真的!

由于我測过,childNodes.length的訪问时间与childNodes.length的值成正比!)这很耗费。所以预先把nodes.length保存到js变量。当然能够提高遍历的性能。

 

相同是函数调用,用户自己定义函数的效率又远远低于语言内建函数,由于后者是对引擎本地方法的包装。而引擎一般是c,c++,java写的。

进一步,相同的功能。语言内建构造的开销通常又比内建函数调用要效率高,由于前者在JS代码的parse阶段就能够确定和优化。

 

所以第四原则就是尽量使用语言本身的构造和内建函数。

 

这里有一个样例是高性能的String.format方法。String.format传统的实现方式是用String.replace(regex, func),在pattern包括n个占位符(包括反复的)时。自己定义函数func就被调用n次。

而这个高性能实现中。每次format调用所作的仅仅是一次Array.join然后一次String.replace(regex, string)的操作,两者都是引擎内建方法,而不会有不论什么自己定义函数调用。两次内建方法调用和n次的自己定义方法调用,这就是性能上的区别。

 

相同是内建特性。性能上也还是有区别的。比如在JScript中对于arguments的訪问性能就非常差,差点儿赶上一次函数调用了。因此假设一个可变參数的简单函数成为性能瓶颈的时候,能够将其内部做一些改变,不要訪问arguments,而是通过对參数的显式推断来处理。

 

比方:

 

Java代码

function sum() {   

    varr = 0;   

   for (var i = 0; i < arguments.length; i++) {   

       r += arguments[i];   

   }   

   return r;   

}  

function sum() {

  var r = 0;

  for (var i = 0; i < arguments.length; i++) {

    r+= arguments[i];

   }

  return r;

}

 

这个sum通常调用的时候个数是较少的。我们希望改进它在參数较少时的性能。

假设改成:

 

Java代码

function sum() {   

   switch (arguments.length) {   

       case 1: return arguments[0];   

       case 2: return arguments[0] + arguments[1];   

       case 3: return arguments[0] + arguments[1] + arguments[2];   

       case 4: return arguments[0] + arguments[1] + arguments[2] +arguments[3];   

       default:   

           var r = 0;   

           for (var i = 0; i < arguments.length; i++) {   

                r += arguments[i];   

            }   

           return r;   

   }   

}  

function sum() {

  switch (arguments.length) {

   case 1: return arguments[0];

   case 2: return arguments[0] + arguments[1];

   case 3: return arguments[0] + arguments[1] + arguments[2];

   case 4: return arguments[0] + arguments[1] + arguments[2] +arguments[3];

   default:

    var r = 0;

    for (var i = 0; i < arguments.length; i++) {

     r += arguments[i];

    }

    return r;

   }

}

 

事实上并不会有多少提高,可是假设改成:

 

Java代码

function sum(a, b, c, d, e, f, g) {   

   var r = a ? b ?

c ?

d ? e ?

f ?

a + b + c + d + e + f : a + b + c + d +e : a + b + c + d : a + b + c : a + b : a : 0;   

   if (g === undefined) return r;   

   for (var i = 6; i < arguments.length; i++) {   

       r += arguments[i];   

   }   

   return r;   

}  

function sum(a, b, c, d, e, f, g) {

  var r = a ? b ?

c ?

d ? e ?

f ?

a + b + c + d + e + f : a + b + c + d +e : a + b + c + d : a + b + c : a + b : a : 0;

   if(g === undefined) return r;

  for (var i = 6; i < arguments.length; i++) {

    r+= arguments[i];

   }

  return r;

}

 

就会提高非常多(至少快1倍)。

 

最后是第五原则。也往往是真实应用中最重要的性能障碍,那就是尽量降低不必要的对象创建。

 

本身创建对象是有一定的代价的。可是这个代价事实上并不大。

最根本的问题是因为JScript愚蠢之极的垃圾回收调度算法,导致随着对象个数的添加。性能严重下降(据微软的人自己说复杂度是O(n^2))。

 

比方我们常见的字符串拼接问题,经过我的測试验证。单纯的多次创建字符串对象事实上根本不是性能差的原因。要命的是在对象创建期间的无谓的垃圾回收的开销。

而Array.join的方式,不会创建中间字符串对象,因此就降低了那该死的垃圾回收的开销。

 

因此,假设我们能把大规模对象创建转化为单一语句。则其性能会得到极大的提高。比如通过构造代码然后eval——实际上PIES项目中正在依据这个想法来做一个专门的大规模对象产生器……

 

好了上面就是偶总结的JS优化五大原则。

 

除了这些原则以外,另一些特殊情况。如DOM的遍历,以后有时间再做讨论。

 

转载于:https://www.cnblogs.com/ljbguanli/p/7105201.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值