• 写性能更好的代码


    因为js最初是一个解释型语言,执行速度要比编译型语言慢得多。chrome是第一款内置优化引擎,将js编译成本地代码的浏览器。此后,主浏览器
    纷纷效仿,陆续实现了js的编译执行。即使到了编译执行js的新阶段,仍然会存在效率低的代码。不过,还是有一些方式可以改进代码的整体性能

    避免全局查找
    随着作用域数量的增加,访问当前作用域以外的变量的时间也在增加。访问全局变量总是要比访问局部变量慢,因为需要遍历作用域链。

    function updataUI(){
        var imgs = document.getElementsByTagName('img');
        for(var i=0,len=imgs.length; i<len; i++){
            imgs[i].title = document.title + 'images' + i;
        }
        var msg = document.getElementById('msg');
        msg.innerHTML = 'Update complete';
    }

    包含了三个对于全局document对象的引用。如果在页面上有多个图片,那么for循环中的document引用就会执行多次甚至上百次,
    每次都会要进行作用域链查找。通常创建一个指向document对象都局部变量,就可以一次限制来改进这个函数的性能。

    function updataUI(){
        var doc = document;
        var imgs = doc.getElementsByTagName('img');
        for(var i=0,len=imgs.length; i<len; i++){
            imgs[i].title = doc.title + 'images' + i;
        }
        var msg = doc.getElementById('msg');
        msg.innerHTML = 'Update complete';
    }

    将在一个函数中会用到多次的全局对象存储为局部变量总是没错的。

    避免不必要的属性查找
    1、O(1)表示常数值,无论有多少个值,需要获取常量值的时间都一样。获取常量值是非常高效的过程

    var value = 5;
    var sum = 10 + value;
    alert(sum);

    该代码进行了四次常量值查找:数字5,变量value,数字10和变量sum。这段代码的整体复杂度被认为O(1)

    2、在js中访问数组也是O(1)操作,和简单的变量查找效率一样

    var values = [5,10];
    var sum = values[0] + values[1];
    alert(sum)

    3、使用变量和数组要比访问对象上的属性更有效率,后者是一个O(n)操作。对象上的任何属性查找都要比访问变量或者数组花费更长时间,因为必须
    在原型链中对拥有该名称对属性进行一次搜索。简而言之,属性查找越多,执行时间就越长。

    var values = {first:5, second:10};
    var sum = values.first + values.second;
    alert(sum);

    这段代码使用两次属性查找来计算sum对值。进行一两次属性查找并不会导致显著的性能问题,但是进行成百上千次则肯定会减慢执行速度。

    var query = window.location.href.substring(window.location.href.indexOf('?'));

    在这段代码中,有6次属性查找:window.location.href.substring()有3次,window.location.href.indexOf()又有3次。
    只要数一数代码的点的数量,就可以确定属性查找的次数了。

    var url = window.location.href;
    var query = url.substring(url.indexOf('?'));

    这个版本的代码只有4次属性查找,相对于原始版本节省了33%;

    优化循环

    for(var i=0; i<values.length; i++){
        process(values[i]);
    }

    这段代码中变量i从0递增到values数组中的元素总数。假设值的处理顺序无关紧要,那么循环改为i减值

    for(var i=values.length; i>=0; i--){
        process(values[i]);
    }

    这里,变量i每次循环之后都会减1。在这个过程中,将终止条件从value.length的O(n)调用简化成了0的O(l)调用。由于循环体只有一个语句
    无法进行进一步的优化,不过循环还能改成后测试循环,

    var i=values.length - 1;
    if(i > -1){
       do{
           process(value[i])
       }while(--i >= 0);
    }    

    此处主要的优化是将终止条件和自减操作符组合成了单个语句。记住使用‘后测试’循环时必须确保要处理的值至少有一个。空数组会导致多余的
    一次循环而'前测试'循环则可以避免。

    展开循环
    当循环的次数是确定的,消除循环并使用多次函数调用往往更快。

    for(var i=3; i>=0; i++){
        process(value[i]);
    }

    改成

    process(value[0]);
    process(value[1]);
    process(value[2]);

    这样展开循环可以消除建立循环和处理终止条件的额外开销


    四、避免双重解释

    eval('alert("hello world !")');
    setTimeout('alert("hello world !")',500);

    在以上例子中,都要解析包含了js代码的字符串。这个操作是不能初始的解析过程中完成的,因为代码是包含在字符串中的,也就是js代码运行的同时
    必须新启动一个解析新的代码

    alert('hello world !');
    setTimeout(function(){
        alert('hello world !');
    },500)

    如果要提高代码性能,尽可能避免出现需要按照js解释的字符串。

    原生方法较快
    原生方法是用诸如c/c++之类的编译语言写出来的,所以要比js的快很多很多,js中最容易被忘记的就是可以在math对象中找到复杂的数学运算,这些方法比
    任何用js写的同样的方法如正弦,余弦快的多


    多个变量声明

    //4个语句-很浪费
    var count = 5;
    var color = 'blue';
    var values = [1,2,3];
    var now = new Date();

    js代码中多语句数量也影响所执行多操作的速度。完成多个操作的单个语句要比完成单个操作的多个语句快。所以,就要找出可以组合在一起的语句,
    以减少脚本的执行时间。

    var count = 5, color = 'blue', values = [1,2,3], now = new Date();

    此处,变量声明只用了一个var语句,之间由逗号隔开。在大多数情况下这种优化都非常容易做,并且要比单个变量声明快很多

    使用数组和对象字面量

    //用4个语句创建和初始化数组-浪费
    var values = new Array();
    values[0] = 123;
    values[1] = 456;
    values[2] = 789;
    //用4个语句创建和初始化数组-浪费
    var person = new Object();
    person.name = 'Nicholas';
    person.age = 29;
    person.sayName = function(){
        alert(this.name);
    }

    这段代码中,只创建和初始化了一个数组和一个对象。各用了4个语句:一个调用构造函数,其他3个分配数据,

    //用1个语句创建和初始化数组
    var values = [123,456,789];
    
    
    //用1个语句创建和初始化对象
    var person = {
        name: 'Nicholas',
        age: 29,
        sayName: function(){
            alert(this.name);
        }
    }

    重写后的代码只包含两条语句,一个创建和初始化数组,另一条创建和初始化对象。之前用了八条语句的东西现在只用了两条,减少了75%的语句量
    在成千上万行js的苦衷,这些优化的价值更大。


    优化dom
    1、最小化现场更新
    createDocumentFragment()创建一个虚拟的节点对象,或者说,是用来创建文档碎片节点。它可以包含各种类型的节点,在创建之初是空的

    var list = document.getElementById('myList'),item,i;
    for(i=0; i<10; i++){
        item = document.createElement('li');
        list.appendChild(item);
        item.appendChild(document.createTextNode('item'+i));
    }

    这段代码为列表添加了10个项目。添加每个项目时,都有2个现场更新:一个添加<li>元素,另一个给它添加文本节点。这样添加10个项目,这个操作总共完成
    20个现场更新

    var list = document.getElementById('myList'),item,i,
    fragment = document.createDocumentFragment();
    
    for(i=0; i<10; i++){
        item = document.createElement('li');
        fragment.appendChild(item);
        item.appendChild(document.createTextNode('item'+i));
    }
    list.appendChild(fragment);

    在这个例子中只有一次现场更新,它发生在所有项目都创建好之后。文档片段作为一个临时都占位符,放置新创建都项目。然后使用appendChild()将所有
    项目添加到列表中。记住,当给appendChild()传入文档片段时,只有片段中当子节点被添加到目标,片段本身不会被添加的。

    2、使用innerHTML
    当把innerHTML设置为某个值时,后台会创建一个HTML解析器,然后使用内部当dom调用来创建dom结构,而非基于js的dom调用。由于内部方法时编译好的而
    非解释执行的,所以执行要快的多。

    var list = document.getElementById('myList'),i;
    for(i=0; i<10; i++){
        list.innerHTML += '<li>item'+i+'</li>';
    }

    使用innerhtml的关键在于最小化调用它的次数

    var list = document.getElementById('myList'),i,html='';
    for(i=0; i<10; i++){
        html += '<li>item'+i+'</li>';
    }
    list.innerHTML = html;

    这段代码构建了一个html字符串,然后将其指定到list.innerHTML,便创建了需要到dom结构。

  • 相关阅读:
    ubuntu系统下安装最新版的MySQL
    scp本地服务器和远程服务器拷贝文件
    linux设置环境变量
    PHP程序员玩转Linux系列-lnmp环境的搭建
    nginx与负载均衡
    Linux下vim的常用命令总结
    nginx与location规则
    ssh秘钥对免密码登陆
    ubuntu下安装php pdo扩展和导入数据库
    ArrayList的删除实现
  • 原文地址:https://www.cnblogs.com/wzndkj/p/8949264.html
Copyright © 2020-2023  润新知