提速,让你的javascript跑的更快!

怎么样才能使你的javascript跑的更快,诀窍就是javascript编译的过程中占用较少的资源,也就是提高javascript的运行性能。以下,我从javascript编程过程中常见的几个方面进行阐述:

(一)作用域

想要掌握javascript,理解javascript中变量的查找机制是不可缺少的,(大家都懂,小弟就再赘述一下,加强一下我等小白理解)javascript中对于变量的查找都是先从局部范围查找,局部范围不存在,再向上一级作用域往中查找,直到大object,如果查到的话,就会返回相应的值或引用,如果不存在,便会报错,小U(undefined)就会出现.

关于作用域,其实也就是变量的查找的性能解决,主要体现在向上查找:

例1:


function foo(){
  var a = document.getElementById("a");
  var b = document.getElementById("b");
}
一眼看感觉,以上程序完成正确,是,完全正确,干干净净的原生javascript,既然是提速,就要想办法让它的性能更优化,稍微修改如下:
function foo(){
  var doc = document;
  var a = doc.getElementById("a");
  var b = doc.getElementById("b");
}

大家可能会想,这不一样吗,但其实不一样猫腻就出现在document身上,document为全局对象,想要引用到document就会一级级往上找,每引用一次,就会需要重新查找一遍。所以,为了消除document对象获取的每次查找,可以将document对象保存在局部变量中,以后的每次document对象的查找就直接可以调用当前的局部变量,节约内存。

其实,以上代码还可以更加优化,小白们,举手,给糖吃:

function foo(){
  var doc = document,
    a = doc.getElementById("a"),
    b = doc.getElementById("b");
}


以上例子,想要说明大家在编程的过程,需要引用全局变量或者上一级的变量时,如果引用的次数较多,可以将此变量以局部变量的形式保存在当前作用域范围内,可以避免对变量的数次查询,提高代码的性能。局部变量的使用还可以提高引擎的垃圾处理,节约内存,何乐而不为呢,是不 ?

(二)对象的属性

javascript中“一切皆对象”,看着简单,能够真正理解,并灵活运用的境界,那可不是我等小白可以触摸的,仅仅仰望而已!

有对象,就会有属性,有属性,就会有引用,对了,关键就在引用!

例2:

function foo(){
  var doc = document,
    a = doc.getElementById("a"),
    b = doc.getElementById("b");
    a.style.width = "100px";
    a.style.height = "100px";
    a.style.border = "1px solid red";
}

在作优化以前,先了解一下,javascript中一些算法复杂度问题。

(1)变量和数组的运用,算法复杂度为O(1)。

(2)对象的属性的引用,算法复杂度为O(n)。

从例2可以看出:调用a.sytle.width,这段代码的算法复杂度为O(2),因为它引用了两次属性。可以看出,如果代码中引用的属性越多或越深,代码相应的算法复杂度便会增高,代码的性能便会降低。

通过以上的简单介绍,大家一定可以轻松优化这段代码,继续小白一下,把代码贴给大家(手下留情,勿扔香蕉皮)

例3:

function foo(){
  var doc = document,
    a = doc.getElementById("a"),
    b = doc.getElementById("b"),
    style = a.style;
    
    style.width = "100px";
    style.height = "100px";
    style.border = "1px solid red";
}
这样是不是可以能够减少对属性的查找呢,挺简单吧,轻轻的多敲几个代码,便有意想不到效果!

(三)dom

javascript的编写离不开对dom的操作,在页面初次渲染(render)成功后,如果在对页面中的dom结构进行操作,便会导致页面的repaint或者reflow,repaint 和reflow过程会占用大量的内存。但,repaint和reflow在javascript编程中又是不可避免的,最优的选择只能是减少repaint 和reflow的发生。

(1)获取某一元素的offsetWidth,offsetHeight,scrollWidth,scrollHeight等属性时,都会促使文档流的reflow,所以,如果需要多次的获得以上的属性值,为了能够减少reflow的次数,可以将初次获得的值存入局部变量中,以便多次引用,减小促发reflow的次数。

(2)修改某一元素的style值会触发repaint,多次触发同样会浪费资源,影响性能,如上图例3,例3中多次对style对象的值进行修改,可以通过以下方式对代码进行优化,减少repaint的次数

function foo(){
  var doc = document,
    a = doc.getElementById("a"),
    b = doc.getElementById("b"),
  style = a.style;

  a.style.display = "none";
  
  style.width = "100px";
  style.height = "100px";
  style.border = "1px solid red";

  a.style.display = "block";
}

从上图可以看出:在修改元素a的style对象前先将元素a隐藏,然后对a的style进行修改,修改结束后,再将a显示,减少repaint的发生。

(3)将大量的数据展现到前端页面,免不了对文档进行大量的元素的添加,元素的添加同样会引起reflow,如果数据量大的话,添加次数相应增加,reflow次数同样增加,如下图:

function foo(){
  var doc = document, 
    parentNode = doc.getElementById("container");
  for(var i = 0,len = 50; i < len; i ++){
    var a = doc.createElement("div");
    parentNode.appendChild(a);
  }    
}

上面的例子,假设需要往parentNode中添加50个div,每添加一次就会引起一次reflow,完成添加,将会引起50次reflow,有没有什么更好的解决办法呢,当然是有的,看下图:

function foo(){
  var doc = document, 
    fragment = doc.createDocumentFragment,
    parentNode = doc.getElementById("container");
  for(var i = 0,len = 50; i < len; i ++){
    var a = doc.createElement("div");
    fragment.appendChild(a);
  }
  parentNode.appendChile(fragment);    
}
从上图可以看出,先创建一个片段fragment,然后将需要添加的元素先添加到fragment中,添加完成后,再将fragmeng添加到parentNode中,reflow一次便可以将所有元素添加到parentNode下。

(4)除了添加元素以外,对元素的修改同样会发生reflow,解决的办法如下:

function foo(){
  var doc = document, 
    node = doc.getElementById("alter"),
    newNode = node.cloneNode(true);
    
    .....对newNode进行修改!
    doc.replaceChild(newNode,node);   
}

其实就是解决办法就是将需要修改的元素先复制一份,对复制元素进行修改,修改完成后替换原来的元素,减小reflow的多次发生。

哎呦喂,终于写完了,现在有点想吐的感觉,希望这种写到想吐的感觉,能给大家一点帮助!

 

转载于:https://my.oschina.net/u/564368/blog/124156

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值