zoukankan      html  css  js  c++  java
  • 读书笔记(03)

    coding

    作用域链查找

    作用域链的查找是逐层向上查找。查找的层次越多,速度越慢。随着硬件性能的提升和浏览器引擎的优化,这个慢我们基本可以忽略。

    除了层级查找损耗的问题,变量的修改应只在局部环境进行,尽量避免在局部环境下去操作修改父级变量的值。(react/vue 单向数据流的数据传输方式)

    优化方法:声明一个变量存储引用(该方法应用甚多)

    不必要的属性查找

    // 未优化(window.location.href 3*2 6次)
    // 未优化(window.location.href 3*2 6次)
    var query = window.location.href.substring(window.location.href.indexOf('?'));
    
    // 优化后(3次,以后多次调用url,查询次数不会增加)
    var url = window.location.href;
    var query = url.substring(url.indexOf('?'));
    url = null;
    

    window.location.href

    函数里面声明的变量,在函数调用栈执行后退出时,会自动清除引用。而全局变量和闭包则会与之相反,继续保存,所以使用用后需手动标记清除,以免造成内存泄漏。

    优化循环

    1. 减值迭代
    2. 简化终止条件
    3. 简化循环体
    4. 使用后测试循环

    减值迭代

    日常应用不多,与增值迭代的区别,就在i存储的值。减值迭代i的值不断在变小,存储的空间也在变小。

    但在前端极少需要遍历上万次上亿次的数据,上千上百都很少,所以这个优化可忽略。而且我们遍历的顺序一般都是从数组头部开始,所以增值迭代应用的更多。

    // 增值迭代(用的较多)
    for(var i = 0; i < len; i++) {
        //...
    }
    
    // 减值迭代
    for(var i = len - 1; i >= 0 ; i--) {
        //...
    }
    

    简化终止条件 (常用)

    终止条件应该是一个固定值判断,应避免在终止条件上做其他运算(属性查找等)。

    // 未优化,每次循环都会去计算数组长度
    var arr = ['HTML', 'CSS', 'JavaScript'];
    for (var i = 0; i < arr.length; i++) {
        //...
    }
    
    // 优化后
    for (var i = 0, len = arr.length; i < len; i++) {
        //...
    }
    // 声明了一个变量len用于储存数组长度,只会计算一次
    

    简化循环体

    循环体的代码应该着重于只需要遍历处理的代码,其他无关代码应放置到循环体外面。

    后测试循环

    最常用的for循环和while循环都是前测试循环。而do-while这种后测试循环,可以避免最初终止条件的计算,因此运行更快。

    前测试循环(for/while),可能一次都不会执行循环体

    后测试循环(do...while),至少执行一次

    用确定索引值更快

    // for循环遍历
    var arr = ['HTML', 'CSS', 'JavaScript'];
    for (let i = 0, len = arr.length; i < len; i++) {
        arr[i];
    }
    
    // 确定索引值
    arr[0]; 
    arr[1]; 
    arr[2];
    

    其他

    1. 原生方法较快(Math)
    2. switch语句较快 (多个if情况下)
    3. 位运算符较快

    TIPS: 判断优化,最可能的到最不可能的顺序组织(if/switch)

    最小语句数

    符合 write less, do more 的代码追求

    多个变量声明合并

    // 多个var声明
    var name = 'KenTsang';
    var age = 28;
    var job = 'Developer';
    
    // 合并一个var声明
    var name = 'KenTsang',
        age = 27,
        job = 'Developer';
    

    插入迭代值

    // 优化前
    var name = value[i];
    i++;
    
    // 优化后
    var name = value[i++];
    

    数组/对象字面量

    创建引用类型可以使用构造函数和字面量两种方式,不过日常习惯都使用字面量,因为语句更简洁,写起来更像数据封装。

    // 字面量
    var arr = [1, 2, 3, 4];
    var obj = {
        name: 'KenTsang'
    }
    
    // 构造函数
    var arr = new Array(1, 2, 3, 4);
    var obj = new Object();
    obj.name = 'KenTsang';
    

    DOM优化交互

    最小现场更新

    现场更新:一旦你需要访问的 DOM 部分是已经显示的页面的一部分,那么你就是在进行一个现场更新

    文档片段

    文档片段相当一个临时的占位符,只有片段中的内容会被添加到DOM上,片段本身并不会被添加。

    // 代码片段标签
    var ele  = document.getElementById('ul');
    var fragment = document.createDocumentFragment();
    var browsers = ['Firefox', 'Chrome', 'Opera', 
        'Safari', 'IE'];
    
    browsers.forEach(function(browser) {
        var li = document.createElement('li');
        li.textContent = browser;
        fragment.appendChild(li);
    });
    
    // 只会操作一次DOM
    ele.appendChild(fragment);
    

    innerHTML

    合并插入代码一次性设置innerHTML。

    // 优化前:操作多次DOM
    var list = document.getElementById("myList");
    for (var i=0; i < 10; i++) {
        list.innerHTML += "<li>Item " + i + "</li>";
    }
    
    // 优化后:操作一次DOM
    var innerHtml = '';
    for (var i = 0; i < 10; i++) {
        innerHtml += '<li>Item' + i + '</li>';
    }
    list.innerHTML = innerHtml;
    

    事件代理(事件委托)

    通过事件流——冒泡机制实现代理,子元素事件触发冒泡到父元素,由父元素绑定一个事件进行统一处理,避免多个事件绑定影响性能。

    事件冒泡

    <ul class="list">
        <li class="item">HTML</li>
        <li class="item">CSS</li>
        <li class="item">JavaScript</li>
    </ul>
    
    var listEle = document.getElementById('list');
    
    listEle.addEventListener('click', function(event) {
        if (event.target.className.indexOf('item') > -1) {
            console.log(event.target.innerHTML); 
        }
    })
    
    // jquery
    $('#list').on('click', '.item', function(event){
        console.log($(this).html());
    })
    

    注意HTMLCollection

    任何时候要访问 HTMLCollection,不管它是一个属性还是一个方法,都是在文档上进行一个查询,这个查询开销很昂贵。

    // 一个死循环例子
    <a href="">link</a>
        
    var existLinkEle = document.getElementsByTagName('a');
    for (var i = 0; i < existLinkEle.length; i++) {     
        console.log(i);
        var linkEle = document.createElement('a');
        document.body.appendChild(linkEle);
    }
    // body会不断地插入a标签
    

    因为existLinkEle.length每次循环都会重新计算页面a节点的数量,而得到的值一直递增。

    // 优化(一个变量存储引用)
    var len = existLinkEle.length;
    for (var i = 0; i < len; i++) {
        //...
    }
    

    返回HTMLCollection对象情况有:

    1. document.getElementByTagName()
    2. 获取元素的childNodes属性
    3. 获取元素的attributes属性
    4. document.forms,document.images

    参考文档

    作者:以乐之名
    本文原创,有不当的地方欢迎指出。转载请指明出处。

  • 相关阅读:
    08-蓝图&单元测试
    07-多对多操作
    JAVA 判断字符串是否可转化为JSONObject、JSONArray
    git常用命令
    线程和进程的一些基本概念
    JavaWeb学习总结(七):通过Servlet生成验证码及其应用 (BufferedImage类)
    JavaWeb学习总结(十):Session简单使用
    Ubuntu16.04 安装maven
    Ubuntu16.04 安装redis
    Ubuntu16.04 下安装tomcat
  • 原文地址:https://www.cnblogs.com/kenz520/p/10062094.html
Copyright © 2011-2022 走看看