前端性能优化(2)---JS优化

JS性能优化的主要方式有:

1、避免不必要的DOM操作

浏览器遍历元素的代价是昂贵的,最简单的优化DOM树的查询方案是,当一个元素出现多次的时候,可以将它保存在一个变量中,这样便可以避免多次查询DOM树了。

// 推荐
var myList = "";
var myListHTML = document.getElementById("myList").innerHTML;

for (var i = 0; i < 100; i++) {
  myList += "<span>" + i + "</span>";
}

myListHTML = myList;

// 不推荐
for (var i = 0; i < 100; i++) {
  document.getElementById("myList").innerHTML += "<span>" + i + "</span>";
}
2、缓存数组的长度

循环的操作和Javascript性能非常相关的一部分,通过缓存数组的长度,可以有效地避免每次循环重新计算。

var arr = new Array(1000), len = arr.length,  i;
// 推荐 --数组的长度仅计算一次,然后被缓存
for (i = 0,i < len; i++) {
    ...
}
//不推荐 --数组的长度需要计算1000次
for (i = 0; i < arr.length; i++) {
    ...
}
3、不要再循环中创建函数

没创建一个函数对象是需要占用大量的空间的,所以在一个循环中创建函数是一个不理智的做法,尽量将函数移动到循环之前创建。

//推荐
var data = []
var m = data.length;
var handler = function(data){
    //do something
};
for(var i = 0;i < m; i++) {
    handlerData(data[i], handler);
}

//不推荐
var data = []
for(var i = 0, m = data.length; i < m; i++) {
    handlerData(data[i], function(data){
        //do something
    });
}
4、利用垃圾回收机制回收不再需要的对象

V8引擎中的垃圾回收机制可以判断保存在内存里的对象是活对象还是死对象,判断方法是按照是否有根对象或者活对象含有对它的引用来判断的。若是有根对象或者活对象引用了该对象,则被判定为活对象。所以有时候需要我们手动消除这些引用来通过垃圾回收机制来回收这些对象。

  • 全局变量
    在垃圾回收机制中,根对象被认为是活对象,因此全局对象也就是根对象,所以,在全局作用域中的变量会一直存在,不能被回收。
  • 闭包
    闭包中内部函数引用的变量和形参不会被垃圾回收机制所回收,使得一个变量常驻内存。这样虽然避免了全局变量的污染,但是同时也容易导致内存的泄露。
手动消除不能被垃圾回收机制所释放的对象的主要方法有:
  • delete
    通过delete的方式看可以消除对象中的键值对,从而消除对象的引用,但是对于var声明的全局变量,并不能通过delete操作符进行删除。
//可删除
var o = { x: 1 };
delete o.x; // true
o.x; // undefined
//不可删除
var x = 1;
delete x; // false
x; // 1
---------------------->
function x(){}
delete x; // false
typeof x; // "function"
  • null
    通过将变量或对象的属性设置为null,也可以消除引用。null使得原来引用的对象为空,然后再垃圾回收的时候进行消除。这种方式不会改变对象的结构,比delete要好用。
5、慎用eval()和with()
  • eval()
    eval()函数可以接受一个字符串str作为参数,并把这个参数作为脚本代码来执行。参数情况:(1)如参数是一个表达式则执行表达式;(2)若参数是Javascript语句,则执行其中的Javascript代码。
eval("var a=1");//声明一个变量a并赋值1。
eval("2+3");//执行加运算,并返回运算值。
eval("mytest()");//执行mytest()函数。
eval("{b:2}");//声明一个对象。如果想返回此对象,则需要在对象外面再嵌套一层小括如下:eval("({b:2})"); 

eval()函数再运行时需要条用解析引擎对其内部的字符串进行解释运行,需要消耗大量的内存。

  • with()
    with对象能够使我们很方便的使用某个对象的一些属性,而不用每次都去写对象名.属性 的形式,直接使用对象名。
//使用with对象时
function validate_email(field, alerttxt) {    
    with(field) {
        apos = value.indexOf("@")
        dotpos = value.lastIndexOf(".")
        if(apos < 1 || dotpos - apos < 2)  {
            alert(alerttxt);
            return false
        } else {
            return true
        }
    }
}
//不使用with对象时
function validate_email(field,alerttxt){
    field.apos=value.indexOf("@")
    field.dotpos=value.lastIndexOf(".")
    if (field.apos<1 || field.dotpos-field.apos<2) {
          alert(alerttxt);
          return false
    }else {
          return true
    }
}

通过with包裹的代码块,作用域链将会额外增加一层,降低索引效率,故不建议使用。

6、异步加载第三方内容

当我们无法保证嵌入的第三方内容是否可以正常工作时,可以考虑使用异步加载这些代码,避免阻塞整个页面的加载。
常见的异步加载的方式:

  • async属性
    利用html5的新属性async;
<script type="text/javascript" async="async" src="http://thirdpart/js.js" ></script>
  • JS异步加载
    这种方法是监听页面加载完之后,在页面中加入script,从而达到引入js文件。
(function() {
    function asyncLoad() {
        var src = "http://thirdpart/js.js";
        var urls = src.split(",");
        var len = urls.length
        var x = document.getElementsByTagName('body');
        if(x && x[0]){
            for (var i = 0; i < len; i++) {
                  var s = document.createElement('script');
                      s.type = 'text/javascript';
                      s.async = true;
                      s.src = urls[i];
                      x[0].appendChild(s);
             }
         }
    }
    window.attachEvent ? 
    window.attachEvent('onload', asyncLoad) :
    window.addEventListener('load', asyncLoad, false);
})();
参考文档:

前端开发规范

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容