• 前端开发代码优化



    前端开发规范手册

    参考:https://www.w3cschool.cn/webdevelopment/index.html

    1、html

      1.1  标签中属性值统一使用 双引号

    <!-- Not recommended -->
    <span id='j-hook' class=text>Google</span>
    
    <!-- Recommended -->
    <span id="j-hook" class="text">Google</span>

    2、css

      2.1   模块组织

        2.1.1   Components 最少以两个单词命名,通过 - 分离,例如:

    • 点赞按钮 (.like-button)
    • 搜索框 (.search-form)
    • 文章卡片 (.article-card)

    3、js

      3.1函数/方法注释

    1. 函数/方法注释必须包含函数说明,有参数和返回值时必须使用注释标识。;
    2. 参数和返回值注释必须包含类型信息和说明;
    3. 当函数是内部函数,外部不可访问时,可以使用 @inner 标识;
    /**
     * 函数描述
     *
     * @param {string} p1 参数1的说明
     * @param {string} p2 参数2的说明,比较长
     *     那就换行了.
     * @param {number=} p3 参数3的说明(可选)
     * @return {Object} 返回值描述
     */
    function foo(p1, p2, p3) {
        var p3 = p3 || 10;
        return {
            p1: p1,
            p2: p2,
            p3: p3
        };
    }

       3.2性能优化

        避免不必要的 DOM 操作

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

    // Recommended
    var myList = "";
    var myListHTML = document.getElementById("myList").innerHTML;
    
    for (var i = 0; i < 100; i++) {
      myList += "<span>" + i + "</span>";
    }
    
    myListHTML = myList;
    
    // Not recommended
    for (var i = 0; i < 100; i++) {
      document.getElementById("myList").innerHTML += "<span>" + i + "</span>";
    }

    即:每次DOM对象都保存到一个变量中。

    4、 


    可维护的JavaScript代码

    1、.所有的 变量和函数的声明在作用域的最前面

    2、全局作用域的变量尽可能少,有些函数需要用到函数外面一层的变量时,可以使用闭包函数把这个变量放到函数内,隔绝全局变量。

       全局作用需要变量的话可以设置一个全局作用域的对象( glob$ = { } ),其它的变量挂在这个对象下。

    3、闭包函数中最好不雅设一个变量指向DOM对象,DOM对象的属性再指向这个闭包函数内的对象。(防止内存溢出)

    4、事件绑定用onclick创建事件,会被同名覆盖掉,


    高性能的JavaScript

    一、加载和执行

    把js放在</body>结束标签之前而不是<head></head>标签内部能够避免浏览器阻塞,提升用户体验,已经算是一个常识。这个常识的背后,涉及到了浏览器单进程的概念。

    事实上,多数浏览器使用单一进程来处理用户界面(UI)刷新和javascript脚本执行,所以同一时刻只能做一件事。

    这里说的用户界面刷新,指的是我们“所能看到的UI”变化(比如点击一个按钮,会出现按钮被按下去的效果)。换句话来说,处理UI就无法处理javascript,反之亦然。所以如果一份运行时间很长的js脚本放在页面顶端,会阻塞之后页面的下载和渲染,给用户的感觉就是“页面一片空白卡死不会动”。

    虽然现在网速和浏览器的效率已经得到了巨大的提升,但随着移动端的兴起以及前端框架如VueReact的大量使用,这个问题还是非常值得我们注意的。

    二、数据存取

    首先对于数据的存取,有以下这么一句关键:

    每一个js函数都会带有一个叫做[[Scope]]的内部属性,也就是该函数的作用域链,它决定了哪些数据能被函数访问。

    书上详细介绍了作用域链执行上下文活动对象全局对象闭包等概念,在这里就不进行复述了。用我自己理解的话来说,就是一个函数若要使用一个变量,它会从最近的地方,也就是定义在函数内部的局部变量里面去找;若没有找到,则往更远处的全局变量(或者上一级作用域)里面去找。恰恰是这个“找”的过程,产生了性能的问题。书上使用了“解析标识符”来表述“找”这个动作,而js性能恰恰是随着解析标识符深度的增加而降低,所以在最佳实践里,往往是通过把一个较深的变量赋值给一个局部变量,在函数内部直接调用这个局部变量来提升性能。

    说完变量,就到了方法。在js中一切皆对象,然而js的对象是基于原型而来,这就引出了一个原型链的概念。与前文关于解析标识符的原理类似,要调用一个对象中的方法,首先会从这个对象实例中查找,若找不到,则会沿着其原型链一步一步由近到远地往上查找,其性能也是随之下降的。

    另外,书上也讨论到了关于“嵌套成员”的问题。比如window.location.href,它会先找到window对象,然后查找嵌套于内的location对象,再找到这里面的href属性,前前后后套了多层,在性能上也有着一定的花销。所以在实际的编码过程中,我们更多时候会面对的往往是这种嵌套成员的问题,时刻记得缓存对象成员的值,在执行完毕后利用cacheObj = null的方式释放缓存,可以有效地提高性能,如下例子:

    // bad
    document.querySelector('.xxx').style.margin = 10 + 'px'
    document.querySelector('.xxx').style.padding = 10 + 'px'
    document.querySelector('.xxx').style.color = 'pink'
    
    // good
    let xxxStyle = document.querySelector('.xxx').style
    xxxStyle.margin = 10 + 'px'
    xxxStyle.padding = 10 + 'px'
    xxxStyle.color = 'pink'
    xxxStyle = null

    三、浏览器中的DOM

    这一章节详细介绍了关于dom操作的一系列问题。首先要明确一个知识点就是dom操作是具有“天生就慢”的问题。为什么会如此呢?因为在浏览器里面,处理html和js是两套不同的机制,他们通过接口来进行联系的。引用书中的原话,就是可以把html和js理解为两座岛,他们之间需要一座桥来进行沟通,而过桥则会产生时间与成本上面的开销,也因此引起了性能的问题。这一章节通过分析不同的dom操作函数,来综合对比了各种方法的速度。

    dom操作往往容易引起浏览器的重绘与重排。重排,指的是页面的布局和几何属性改变时所发生的事情;重绘,是指把dom元素绘制到屏幕上面的过程。

    会造成性能问题的,往往来自于重排,因为浏览器需要重新计算页面所有元素的大小与位置,然后把它们安置在正确的地方。所以,要提升页面的性能,很重要的一个举措就是避免页面的重排。

    值得注意的是,并非只有在修改页面元素的大小和位置的时候才会引发重排,在获取的时候浏览器也会出发重排,以返回正确的值。

    然而很多时候我们不得不直接操作dom,尽管它们会引起重排和重绘。书上给出了几个方案,都能有效提升性能。其实方法和上文关于js缓存局部变量的方法类似,也是通过缓存的机制,减少对于dom元素属性的查找,以及批量修改变量再一次性更新dom的办法去减少查询与修改。

    除此以外,让元素脱离文档流也是一个很好的方法。因为元素一旦脱离文档流,它对其他元素的影响几乎为零,性能的损耗就能够有效局限于一个较小的范围。

    讲完重排与重绘,往dom元素上绑定事件也是引起性能问题的元凶。利用浏览器自带的冒泡或捕获机制,可以通过事件委托的方式减少事件处理器的数量,从而把性能优化得更好。

    四、算法和流程控制

    这一章首先分析了几种循环类型,结论是只有for-in循环的性能最慢,因为每次迭代都会同事搜索实例或原型属性,导致其性能只有其它类型速度的1/7。
    循环在代码中非常常见,既然无法避免,则需要通过尽量减少循环次数,减轻每次循环的工作量的方式提升性能。

    对于条件语句if else或者switch,其性能在现实中并没有太大区别,关键是要正确处理语义化的需求。有的时候也可以使用查表法进行。

    对于递归算法,最好的提升性能方法是缓存上次执行的结果,在下一次递归的时候直接引用而非从头开始计算。

    五、字符串和正则表达式

    六、快速响应的用户界面

    前面五章都是针对JS原生的语法分析性能问题,从这一章开始分析针对用户界面的可感知性能问题。

    由于浏览器是单线程运作的,在处理UI事件的时候无法处理js事件,反之亦然,所以对于耗时过长的js任务来说,可以使用定时器的方法使其让出线程控制权,让浏览器优先处理UI事件以提升用户体验。

    html5新增的web worker允许多开线程,意味着耗时较长、性能损耗较大的js任务可以放到web worker中进行,而无需阻塞浏览器UI线程的执行。值得注意的是,web worker无法使用浏览器相关的资源,所以无法用以进行dom操作等。

    七、Ajax

    ajax技术已经是如今的主流技术,在这里就无需赘述了。书上关于其性能优化的内容,多集中在浏览器资源缓存上。如果能够有效利用浏览器的缓存机制,可以大大减少与服务端的交互,提升性能。

    书上没有提及的是现在逐渐开始流行的fetch API,关于这方面的性能的问题也值得我们研究。

     
  • 相关阅读:
    Java字符串跟ASCII码互转
    java 一款可以与ssm框架完美整合的web报表控件
    使用<c:set>标签配置项目路径
    Linux下部署tomcat及tomcat war包应用程序
    支付宝app支付服务端流程
    文本数据增量导入到mysql
    java 读取mysql中数据 并取出
    实现读取文本数据,在将数据导入mysql
    给一个整形数组,给出一个值,当这个值是数组某些数字的和,求出数组下标的值
    文本数据和mysql 里面的数据比较
  • 原文地址:https://www.cnblogs.com/wfblog/p/8951692.html
Copyright © 2020-2023  润新知