美文网首页
如何提高javascript性能

如何提高javascript性能

作者: Lisa_Guo | 来源:发表于2021-03-12 18:30 被阅读0次

    一、总原则

    减少操作:js引擎,业务代码

    本文主要从变量访问和算法逻辑讨论

    二、变量访问

    数据类型
    数据存放的位置不同决定了数据访问的速度不同。JavaScript中有四种基本的数据类型:

    1. 字面量 (Literal values)
      变量存储的是实际数值。JavaScript字面量类型有:字符串,数字,布尔值,对象,数组,函数, 正则表达式,NULL,undefined

    2. 变量 (Vriables)
      用vars声明的变量用于存储数据值

    3. 数据项 (Array items)

    4. 对象成员 (Object members)

    NOTES:
    a. 前两类存储在栈中,后两项存储在堆中
    b. 前两类访问速度高于后两种

    作用域
    声明一个函数实际是创建一个Function类的实例
    在函数创建时,建立一个[[Scope]]的内部属性,定义了该函数可访问的数据,称为作用域链。创建器作用域链 = 全局变量:browser,window, document等
    在函数运行时,建立一个‘运行期上下文’的内部属性,定义了该函数运行期间作用域链等执行环境。运行期作用域链 = [[Scope]]作用域链 + 局部变量,参数,this,参数等,按照栈的方式存储

    实例1: 定义以下函数

    function add(num1, num2) {
      const sum = num1 + num2;
      return sum
    }
    

    创建期间的作用域链


    image.png

    执行函数时作用域链


    image.png

    实例2: 定义以下闭包

    function assignEvents() {
       var id = "123"
       document.getElementById('save-btn').onclick = function(event) {
          saveDocument(id)
       }
    }
    

    创建期闭包函数作用域链


    image.png

    执行期闭包函数作用域链


    image.png

    结论:变量在作用域链的位置越深越慢,全局最慢,局部最快
    提升:用本地局部变量缓存全局变量等访问速度慢的变量

    三、优化实例

    3.1 局部变量缓存

    多次访问document的函数

    function initUI(){
      var bd = document.body,
      links = document.getElementsByTagName_r("a"),
      i = 0,
      len = links.length;
      while(i < len){
        update(links[i++]);
      }
      document.getElementById("go-btn").onclick = function(){
        start();
      };
      bd.className = "active"
    }
    

    缓存document后

    function initUI(){
        var doc = document,
        bd = doc.body,
        links = doc.getElementsByTagName_r("a"),
        i = 0,
        len = links.length;
        while(i < len){
            update(links[i++]);
        }
        doc.getElementById("go-btn").onclick = function(){
            start();
        };
       bd.className = "active";
    }
    

    3.2 字符串连接

    使运算符时,尽量使用+=,-=、=、=等运算符号,而不是直接进行赋值运算。
    

    实例1
    如果是追加字符串,最好使用s+=anotherStr;而不是要使用s=s+anotherStr

    实例2
    拼接多个字符串

    // bad  
    x+=a; x+=b; x+=c;
    
    /// good    
    x+= a + b + c;
    

    3.3 原型链

    对象的继承是通过原型对象实现的

    实例1
    定义如下对象

    var book = {
       title: "High Performance JavaScript",
       publisher: 'Yahoo'
    }
    
    原型链为 image.png

    实例2
    定义如下对象

    function Book(title, publisher){
        this.title = title;
        this.publisher = publisher;
    }
    Book.prototype.sayTitle = function(){
        alert(this.title);
    };
    var book1 = new Book("High Performance JavaScript", "Yahoo! Press");
    alert(book1 instanceof Book); //true
    alert(book1 instanceof Object); //true
    book1.sayTitle(); //"High Performance JavaScript"
    book1.toString(); //"[object Object]"
    
    image.png

    结论:对象成员在原型链上的位置越深速度越慢
    提升:减少.的操作,缓存对象成员的值

    四、算法与流程控制优化

    4.1 循环语句

    主要进行下面几种优化方案:

    1 减少对象成员和数组项查找次数

    2 减少迭代次数

    3 缓存中间值

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

    上面的代码每次循环要做的操作:

    1. 读取属性:items.length
    2. 执行比较:i < items.length
    3. 判断条件:i < items.length === true
    4. 自加操作:i++
    5. 数据查找:items[i]
    6. 函数调用:process(items[i])

    优化后

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

    4.2 条件判断

    主要是if-else和switch

    1. 将常用的条件放在前面

    if (value < 5) {
        //do something
        // <5为高概率事件
    } else if (value > 5 && value < 10) {
        //do something
        // 5-10为中概率事件
    } else {
        //do something
    }
    

    2 查表法
    适合大量离散数据的条件判断

    | |

    优化后

    
    //define the array of results
    var results = [result0, result1, result2, result3, result4]
    //return the correct result
    return results[value];
    
    

    或使用策略模式

    //define the array of resultsvar results = [result0, result1, result2, result3, result4]//return the correct result
    return results[value];
    

    五、其他优化技巧

    其他参考:
    优化 JS 条件语句的 5 个技巧
    JS性能优化38条”军规”

    相关文章

      网友评论

          本文标题:如何提高javascript性能

          本文链接:https://www.haomeiwen.com/subject/lmmvrktx.html