加载和运行---高性能JavaScript读书笔记(1)

众所周知大多数浏览器是使用单进程处理UI更新和JavaScript运行等多个任务的,而同一时间只能有一个任务被执行,如此说来,JavaScript运行了多长时间就意味着用户得等待浏览器响应需要花多久时间。

从认知上来说,解析器解析一个界面的时候都是从上至下依次解析的,这就是说界面上出现多少个<script>标签(不管是内联还是外部文件),页面下载和解析必须停止等待脚本下载完成并运行完成(注意这里包括运行),这个过程当中,页面解析和用户交互是被完全阻塞的。

Javascript第一条定律:将脚本放在底部。

大家都知道,浏览器在遇到<body>标签之前,不会渲染页面中的任何部分,如果我们把<script>标签全部放在<body>标签之前,大家想想界面是不是一片空白,直至浏览器将所有js都下载并执行后才会去渲染页面,这也就是为什么要将所有<script>标签放在尽可能接近<body>标签底部也就是</body>前的原因。

Javascript第二条定律:将脚本成组打包。

减少引用外部脚本文件的数量,大家相信都会看到一些大型网站需要多次请求JavaScript文件时会将这个文件整合成一个文件,因为这样只需要一个<script>标签而减少性能损失。

书中介绍了运行一个<script>标签来加载两个js文件(但是自己没有试验成功,如果有知道怎么用的,可以告知我,谢谢!)

在此特意说明一下

  • 为什么很多人特别喜欢用外部文件来写js而不用内联js,这是因为1)外部文件易于管理2)浏览器有缓存外部文件的功能,同样一个js文件如果被多个界面共享使用,第二个使用的可以直接从缓存中拿而不用从远程服务器上去下载,省去了好多时间及流量呀
  • 为什么许多人会用CDN(Content Delivery Network)来加载公用js比如说jquery.js,这是因为从别的网站比如说jQuery官网下载jQuery占有的是别人服务器的资源,减轻了本地服务器的负载,节省网站分布式架构的支出成本和运维成本。
  • 上文中讲了将多个js文件打包成一个js文件,可以提高性能,可以试试用Yahoo! Combo handler ,这篇文章介绍了一下http://www.ooso.net/archives/458  不过百度一下js打包工具一大堆,大家可以任意发挥哦

总归一句话就是加载js的时候会阻塞页面渲染,那怎么样让脚本不阻塞页面渲染呢,唯一的方法就是在window.onload发生后开始下载js

Javascript第三条定律:使用非阻塞方式下载js。

第一种方法:为script增加了一个defer属性,defer属性指定的script指明脚本不打算修改DOM,所以代码可以稍后执行。但是defer并不是所有浏览器都支持的。当defer指定的脚本文件被下载时,它不会阻塞浏览器的其它处理过程,所以事实上defer指定的脚本文件是可以与页面中的其它资源并行下载的。任何被指定为defer的脚本文件一定会在DOM加载完成之后才会被执行,也就是在onload事件之前被执行。

第二种方法:动态创建脚本也就是通过js创建script标签指定它的src来加载脚本文件,这种方法使得脚本下载和运行不会阻塞其它页面处理程序,所以你甚至可以把这种动态创建脚本的文件放在head标签当中都没有关系。

动态创建脚本的js如下图所示:

上述动态创建的脚本只要一指定它的src并append到document中,它就会自动执行里面的代码,那怎么样让它加载完成之后执行回调函数或者说如果我要加载多个js文件合格保证它们的顺序呢

看代码吧! 哈哈(因为动态加载的js,浏览器不保证加载的顺序)

另外一种以非阻塞方式获得脚本文件的方法就是使用XHR(XmlHttpRequest脚本注入)

这种方法的主要优点是你可以下载不立即执行的脚本文件,但是缺点就是你要动态加载的js文件必须与当前运行的页面在同一个域中

下面介绍几个动态加载的脚本库

LazyLoad--可以下载多个脚本文件并保证在所有浏览器上保证顺序执行。(虽然可以动态加载多个文件,但还是建议尽可能的减少文件数量,因为每个下载仍然是一个单独的HTTP请求)

Labs.js  它的script方法用于加载js文件,wait方法用于等待文件下载并运行之后执行的回调函数,通过wait方法允许你哪些文件应该等待其它文件,具体用法可以参照labs使用方法

这是我看《高性能JavaScript》第一章中我认为重要的,在些强烈推荐大家看下这本书,确实挺不错的。(文章中的一个问题希望有会的大神能够提点一下我,在此多谢了哦!)

有兴趣的可以去了解一下lab.js和lazyload  这俩挺好用的。哈哈!也可以跟我共同研讨!

时间: 2024-12-21 17:51:38

加载和运行---高性能JavaScript读书笔记(1)的相关文章

高性能javascript读书笔记(三.DOM 编程1)

第三章DOM Script DOM编程 读书笔记 访问和修改DOM元素 浏览器通常要求DOM实现和JavaScript保持相互独立. <!-- 例如IE中,被称为JScript的JavaScript实现位于库文件jscript.dll中,而DOM实现位于另一个库mshtml.dll(内 部代号Trident).这种分离技术允许其他技术和语言,如VBScript,受益于Trident所提供的DOM功能和渲染功能.Safari使用Webkit的WebCore处理DOM和渲染,具有一个分离的JavaS

数据访问---高性能JavaScript读书笔记(2)

对于任何一种编程语言来说,数据存储的位置关系到访问速度! 在JavaScript中的直接量包括字符串string.数字number.布尔值boolean.对象object.数组array.函数function.正则表达式regular expression.空值null.未定义数组undefined.而数组项则需要通过数组的数字索引来访问,对象通过字符串进行索引来访问其成员(这里顺便提一句因为数组项是通过数字进行索引.对象成员是通过字符串进行索引,所以这也就是为什么访问对象成员比访问数组项更慢的

高性能javascript读书笔记(三.DOM 编程2)

重绘和重排版 浏览器下载完所有的HTML标记,Javascript,CSS,图片之后,它解析文件并创建两个内部数据结构 DOM树 表示页面结构渲染树 表示DOM节点如何显示 渲染树中为每个需要显示的DOM树木=节点存放至少一个节点(隐藏DOM元素在选桉树中没有对应节点)渲染树上的节点称为"框"或者"盒",符合CSS模型的定义,将页面元素看作一个具有填充,边距,边框和位置的盒.一 旦DOM树和渲染树构造完毕,浏览器就可以显示(绘制)页面上的元素了. 当DOM改变影响到

DOM访问---高性能JavaScript读书笔记(3)

在JavaScript高级程序设计第一章当中就把JavaScript分成三大部分 所以事实上DOM和BOM是两在独立的部分,它们之间的通信是通过相互之间的功能接口来实现的,这样说来两个独立的部分以功能接口必定会带来性能损耗.这也就是为什么大家一致都说尽量少去访问和修改DOM元素(注意我这里说的是访问和修改,为什么包括访问,请继续往下看  哈哈). 下面用一张图来说明它们各自的作用. 1.在修改DOM元素的时候,我们应该尽量使用innerHTML而不是CreateElement再AppendChi

【Hight Performance Javascript】——脚本加载和运行

脚本加载和运行 当浏览器遇到一个<script>标签时,无法预知javascript是否在<p>标签中添加内容.因此,浏览器停下来,运行javascript代码,然后继续解析.翻译页面. 浏览器必须首先下载外部文件的代码,这要占用一些时间,然后解析并运行代码,这又要占用一些时间.此过程中,页面解析和用户交互是被完全阻塞的. 将脚本放在底部 合并脚本减少个数 延迟脚本(defer) <script src="file1.js" defer></s

高性能javascript 学习笔记(1)

加载和运行 管理浏览器中的javascript代码是个棘手的问题,因为代码运行阻塞了其他浏览器处理过程,诸如用户绘制,每次遇到<script>标签,页面必须停下来等待代码下载(如果是外部的)并执行,然后再继续处理页面其他部分.但是,有几种方法可以减少javascript对性能的影响: 将所有<script>标签放置在页面的底部,紧靠body关闭标签</body>的上方,此法可以保证在脚本运行之前完成解析. 将脚本成组打包.页面的<script>标签越少,页面

Linux进程启动过程分析do_execve(可执行程序的加载和运行)

日期 内核版本 架构 作者 GitHub CSDN 2016-06-06 Linux-4.5 X86 & arm gatieme LinuxDeviceDrivers Linux进程管理与调度-之-进程的描述 execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x86架构下, 其实还实现了一个新的exec的系统调用叫做execveat(自linux-3.

Linux进程启动过程分析do_execve(可执行程序的加载和运行)---Linux进程的管理与调度(十一)

execve系统调用 execve系统调用 我们前面提到了, fork, vfork等复制出来的进程是父进程的一个副本, 那么如何我们想加载新的程序, 可以通过execve来加载和启动新的程序. x86架构下, 其实还实现了一个新的exec的系统调用叫做execveat(自linux-3.19后进入内核) syscalls,x86: Add execveat() system call exec()函数族 exec函数一共有六个,其中execve为内核级系统调用,其他(execl,execle,

Javascript读书笔记:函数定义和函数调用

定义函数 使用function关键字来定义函数,分为两种形式: 声明式函数定义: function add(m,n) { alert(m+n); } 这种方式等同于构造一个Function类的实例的方式: var add = new Function("m", "n", "alert(m+n);"); Function类构造方法的最后一个参数为函数体:"alert(m+n);",前面的都是函数的形参,参数必须是字符串形式的:&