优化JavaScript总结分享(上)

栏目: JavaScript · 发布时间: 6年前

内容简介:本来想整理一篇完整的JavaScript优化知识点出来跟大家讨论分享一下的,但是由于最近个人的时间比较少,所以先整理了两个知识点,之后有时间了再继续整理后面的。不喜欢勿喷,有错误的欢迎大佬指点。2019/05/14/01:30

本来想整理一篇完整的JavaScript优化知识点出来跟大家讨论分享一下的,但是由于最近个人的时间比较少,所以先整理了两个知识点,之后有时间了再继续整理后面的。不喜欢勿喷,有错误的欢迎大佬指点。

1.引用 script标签的优化

2019/05/14/01:30

  • 多数浏览器都是使用单一的进程来处理用户界面(UI)和JavaScript脚本执行,所以同一时刻只能做一件事,因此就会造成浏览器的堵塞状态,JavaScript脚本执行过程耗时越久,浏览器等待响应的时间就越长。(也就是说当页面加载的时候,遇到script标签的时候,页面加载就会被终止,等到JavaScript脚本执行完毕后,再继续加载页面,这样给用户的体验特别不会,很容易首次加载页面的时候出现白屏状态。)

优化方式

  • 传统的方式
    传统的方式就是,把JavaScript的脚本放到head标签之后</body>之前,也就把script标签放到最尾处,来确保页面加载完之后才执行JavaScript脚本,从而达到一些不必要的阻塞。(可能这也是我们平时用得比较多的方式)
  • 延迟JavaScript脚本执行

    1.HTML4script标签扩展了一个Defer属性,指定这个属性的script标签的脚本不会修改DOM,因此代码能安全的延迟执行。加上这个属性的script标签的脚本可以放在DOM的任意位置,当浏览器加载到它是,它会被下载,但不会被执行,所以不能阻塞页面的方面,它会等到页面加载完成后,在windownload()函数之后执行。
<script type="text/javascript" src="./a.js" defer="defer"></script>

<script type="text/javascript">
    console.log("b")
</script>

<script type="text/javascript">
    window.onload = function () {
        console.log("c")
    }
//这个例子,最终输出的顺序是b,a,c
</script>

优化JavaScript总结分享(上)

2.H5的时候,script又扩展了一个async属性,它与defer相同点就是都是采用并行下载,不会在下载的过程造成页面的阻塞情况;不同点就是,它们的执行时机:async加载完之后,自动执行(也就是说,当加载到它的时候,浏览器可以继续往下加载页面,当它加载完之后,它就会自动执行,而不需要等到页面加载完之后再执行,也不用页面加载等它执行完再往后执行);而dafer要等页面加载完成后才会执行。
  • 合拼JavaSript脚本

    因为每个script标签初始下载是=时都会阻塞页面渲染,所以减少页面包含的script标签数量也有助于页面加载性能的优化。(如果页面有很多的script标签,没个script标签都会发送一次http请求( http://tool.oschina.net/jscom... ),从而浪费了很多没必要的时间,我们可以通过某些在线 工具 将多个script标签合拼成一个script标签,最终页面只引用了一个script,也就是只发送了一次http请求,这样加载性能会比之前加载多个script标签快)

2.作用域/链的优化

2019/05/15/02:05

  • JavaScript的作用域同样关系到性能的问题

    • 在es6之前JavaScript没有什么块级作用域所说,只有全局作用域和函数作用域。(没什么块级作用域有时会给我们带很多莫民奇妙的东西),例如:一个经典的面试题:
//结果输出什么?
    for(var i = 0; i<10;i++){
            setTimeout(function () {
                console.log(i)
            },1000)
        }

我们期望的结果是输出0-9。但是结果拼不是我们想这样,这玩(diao)意(mao)既然输出十次10.为什么会这样?因为当setTimeout执行的时候,for循环已经完成,已经变成了10。

怎样解决?(在es6没有到来之前,一般都是同闭包的方法把作用域缓存起来)

for(var i = 0; i<10;i++){
        (function(i){
            setTimeout(function () {
                console.log(i)
            },1000)
        })(i)
    }
//结果输出为0-9

最后输出的结果就跟我们期待的一样了,但是上面使用了闭包,闭包也涉及到作用域链的性能问题;因为闭包的属性包含了与执行环境作用域相同的对象的引用,因此导致闭包里面的变量没办法被销毁,从而占用了更多的内存空间,也有可能导致内存泄漏问题,所以使用闭包时还是要谨慎,它关系到内存以及执行速度。

//上面代码优化后
for(let i = 0; i<10;i++){
            setTimeout(function () {
                console.log(i)
            },1000)
        }

2.尽量使用局部变量缓存全局变量

  • 在实际开发中尽量使用局部变量缓存全局变量,因为,到一个函数多次访问全局变量的时候,会出现一个作用域练查找的过程,全局作用域位置越深找到的时间就越久,因此这也会涉及到性能的执行速度问题。例如:下面这段简单的代码,在浏览器打开执行看到还是挺快的,没什么问题;但是,它三次引用了obj.name这个全局变量,在这个查找的过程中必须遍历整个作用域链,直到找到为止(幸亏这个全局变量比较浅,幸亏,这段代码只引用了三次;要这个全局变量在window对象上面呢,要是这个全局变量会被引用几千万次呢),然后我们可以将这个多次被引用的全局变量,用局部变量存起来,这样无论这个全局变量被引用多次,它都只会查找一次。
let obj = {
        name:"July"
}

function Person() {
    console.log(obj.name +"去吃饭",obj.name +"去睡觉",obj.name +"去打篮球")
}

Person()

//改

let obj = {
        name:"July"
}

function Person() {
    let name = obj.name
    console.log(name +"去吃饭",name +"去睡觉",name +"去打篮球")
}

Person()

3.尽量不要使用动态作用域,因为他们会改变执行环境的作用域链。比如with()语句和try{}catch(){}的catch(){}字句...,它们都会改变执行环境的作用域链。比如下面这段代码:with会把一个包含了obj全部属性的新的可变变量置于作用域链的头部,使得访问obj对象属性速度非常快,但是访问局部变量则变慢了,因此还是尽量避免使用。

let obj = {
    name:"July"
}

function Person() {
    with(obj){
        console.log(name +"去吃饭",name +"去睡觉",name +"去打篮球")
    }
}
Person()

以上所述就是小编给大家介绍的《优化JavaScript总结分享(上)》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Elements of Programming

Elements of Programming

Alexander A. Stepanov、Paul McJones / Addison-Wesley Professional / 2009-6-19 / USD 39.99

Elements of Programming provides a different understanding of programming than is presented elsewhere. Its major premise is that practical programming, like other areas of science and engineering, mus......一起来看看 《Elements of Programming》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具