在讲这个问题之前,先来补充几个知识点,如果对此已经比较了解可以直接跳过
1. 大多数浏览器的组件构成如图
在最底层的三个组件分别是网络,UI后端和js解释器。作用如下:
(1)网络- 用来完成网络调用,例如http请求,它具有平台无关的接口,可以在不同平台上工作
(2)UI 后端- 用来绘制类似组合选择框及对话框等基本组件,具有不特定于某个平台的通用接口,底层使用操作系统的用户接口
(3)JS解释器- 用来解释执行JS代码
ps:上图和知识点主要来自《HOW
BROWSERS WORK: BEHIND THE SCENES OF MODERN WEB BROWSERS》 想深入了解的同学可以重点看下。
2. 大多数浏览器(比如chrome)让一个单线程共用于执行javascrip和更新用户界面。这个线程通常被称为“浏览器UI线程”, 每个时刻只能执行其中一种操作,这意味着当Javascript代码正在执行时用户界面无法响应输入,反之亦然。这样做是因为javascript代码的作用就是操作DOM更新用户界面,用同一个线程来做负责这两件事情可以更高效
3. 浏览器UI线程的工作基于一个简单的队列系统,任务会被保存到队列中直到进程空闲。一旦空闲,队列中的下一个任务就被重新提取出来并运行。这些任务要么是运行javascript代码,要么执行UI更新,包括重绘和重排。
4. 重点再强调下,javascript是单线程运行,千万别被setTimeout()和setInterVal()这种函数迷惑而误以为它是多线程。
ok,基础点讲解完毕,让我们进入正题,来讲解在浏览器中javascript的执行过程。
一、原理
一般而言,<script>标签每次出现都会霸道地让页面等待脚本的解析和执行,无论当前的Javascript是内嵌的还是包含了外链文件,页面的下载和渲染都必须停下来等待脚本执行完成。这在页面的生存周期中是必要的,因为脚本执行过程中可能修改页面内容,一个典型的例子就是在页面中使用document.write()。
当javascript代码是内嵌在html里面时,这点还是比较容易理解,但当javascript是外链文件时稍微有点负载,因为存在一个加载过程,而且浏览器加载好这个js文件之后往往还对其缓存。
首先,我们用以下这个例子来说明下缓存问题
<html>
<head>
<script type='text/javascript' src='js/f2.js'></script>
</head>
<body>
</body>
</html>
第一次打开页面时:
第二次打开页面时:
从上例中可以明显看出,像chrome之类的高版本浏览器会对js文件进行缓存,作用是不言而喻,减少网络请求。
其次,第二个问题,当一个javascript文件被加载时是否会阻塞其他javascript文件或者其他文件的加载。《高性能Javascript》一书中对这个问题做了较好的解答:各种浏览器的低版本的处理是当一个javascript文件在加载时,会同时阻塞页面其他文件的加载(包括其他javascript文件),但IE8,Firfox3.5,Safari 4和Chrome 2都允许并行下载javascript文件,但遗憾的是,javascript下载过程仍然会组舍其他资源的下载,比如图片。尽管javascript脚本的下载过程不会相互影响,但页面仍然必须等待所有的javascript代码下载并执行完成才能继续。
二、技巧
1. 脚本位置
由于脚本会阻塞页面其他资源的下载,因此推荐将所有的<script>标签放到<body>标签的底部,已尽量减少对整个页面下载的影响。
2. 将能合并的js文件合并
3. 无阻塞脚本
现在比较常用的方法就是动态加载执行脚本。你的原理是通过DOM,你几乎可以用Javascript动态创建HTML中的所有内容,其根本在于,<script>标签与页面中其他元素并无差异:都能通过DOM引用,都能在文档中移动,删除和创建。文件在改该<script>元素被添加到页面时开始现在,它不会阻止其他文件下载,只在执行阶段阻塞渲染。特别强调:《高性能javascript》一文中说“这种技术的重点在于:无论何时启动下载,文件的下载和执行都不会阻塞页面其他进程”,这并不是说它在执行不会阻塞其他javascript代码,而是要强调不会阻塞其他资源的下载等其他任务。
具体的代码如下:
function load_script(url, callback) {
var script = document.createElement('script');
script.type = 'text/javascript';
if (script.readyState) { //IE
script.onreadystatechange = function() {
if (script.readyState == 'loaded' || script.readyState == 'complete') {
script.onreadystatechange = null;
callback();
}
}
} else { //others
script.onload = function() {
callback();
}
}
script.src = url;
document.getElementsByTagName('head')[0].appendChild(script);
}
4. 神奇的setTimeout()
这里我不过多的将setTimeout()的原理,有兴趣的读者可以具体去看《高性能javascript》的第六章。我重点强调下,setTimeout的第二个参数并不是一个精确的时间,二是必须在javascript线程空闲时才能运行。利用这个特性,如下代码简单可以实现等待其他js代码执行完毕后再执行function里面的代码。
setTimeout(function(){
// do some before other javascripe codes had processed
}, 25)
但在function里面不要使用document.write()方法,因为执行setTimeout里面函数时往往已经到了页面onload之后,此时再执行document.write 将导致当前页面的内容被清空,因为它会自动触发document.open 方法。
分享到:
相关推荐
这一点是没有争议的,并且在所有浏览器中的行为都是一致的,原因也不难理解:浏览器需要一个稳定的DOM结构,而JavaScript可能会修改DOM(改变DOM结构或修改某个DOM节点),如果在JavaScript执行的同时还继续进行页面的...
之前从JavaScript引擎的解析机制来探索JavaScript...1.1 按HTML文档流顺序执行JavaScript代码首先,读者应该清楚,HTML文档在浏览器中的解析过程是这样的:浏览器是按着文档流从上到下逐步解析页面结构和信息的。Java
任务链是动态的,可以在执行过程中向任务链添加 step ,这是 ocSteps 和其他流行的异步操作库的主要区别(例如 Step, Async.js):不是提供各种规则来定义执行顺序,而是在任务链的执行过程中逐步定义任务链。...
如果通过脚本标签[removed]的src属性来引入外部.js文件,那么它也将按照其语句出现的顺序来执行,而且执行过程是文档加载的一部分。不会因为是外部js文件而延期执行。 2、预编译和执行顺序的关系 首先看如下这段代码...
在本书中我们将给出解答,带你了解浏览器安全的方方面面。本书兼顾攻击者、研究者和使用者三个场景,对大部分攻击都提供了分析思路和防御方案。本书从攻击者常用技巧的“表象”深入介绍浏览器的具体实现方式,让你在...
javaScript文件(下面简称...同样的情况也发生在使用 src 属性加在javaScript的过程中(即外链 javaScript),浏览器必须先花时间下载外链文件中的代码,然后解析并执行它。在这个过程中,页面渲染和用户交互完全被阻塞
虽然现代浏览器可以并行的下载JavaScript(部分浏览器),但考虑到JavaScript的依赖关系,他们的执行依然是按照引入顺序进行的。 本文章记录本人在学习 JavaScript 中看书理解到的一些东西,加深记忆和并且整理记录...
当浏览器遇到[removed]标签的时候,浏览器必须先话时间下载外链的文件然后并执行,在这过程中,页面渲染和用户交互是完全被阻塞的。 脚本放在哪里比较好? 这种情况无疑是存在严重的性能问题的,由于脚本会阻塞页面...
在页面的加载过程中如果可以做到内容的逐步呈现,对于良好的用户体验来说是非常重要的。通常我们也会在wondow对象的onload事件处理函数中做一些事情,但由于脚本阻塞加载和呈现的特性这一方面增加了页面载入时间...
1、在浏览器的控制台(Console)中,输入脚本并执行 2、将JS脚本代码嵌入在HTML页面中执行 1、采用HTML元素事件执行JS代码 事件 : 1、onclick 当元素被点击时执行的操作 ex: 当按钮被点击时,在控制台中输出 ...
3) 脚本执行过程是Web浏览器的HTML解析过程的一部分。脚本按照它们的出现顺序执行。 4) 简单的对话框可用:alert()、 confirm()、 prompt()之一。 5) 时间间隔方法为: setInterval()、 cleraInterval() 。 ...
描述JavaScript是一种高级、解释型的编程语言,用于在Web浏览器中创建交互式网页和应用程序。它具有以下特点: 强大的功能:JavaScript提供了丰富的内置功能和API,包括处理文本、数字、日期、数组、对象等。它还...
2.1.2 脚本执行顺序 2.1.3 大小写敏感 2.1.4 空白字符 2.1.5 分号 2.1.6 块 2.2 数值类型 2.2.1 整型和浮点数值 2.2.2 八进制和十六进制 2.3 变量 2.3.1 变量标识符 2.3.2 变量申明 2.3.3 变量作用域 2.4 弱类型 2.5...
JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长。浏览器在下载和执行脚本时出现阻塞的原因在于,脚本可能会改变页面或 JavaScript 的命名空间,它们对后面页面内容造成影响。 一个典型的例子就是...
它可以让你在浏览器中的Javascript代码调用Web服务器上的Java,就像在Java代码就在浏览器中一样。 DWR主要包括两部分: 在服务器上运行的Servlet来处理请求并把结果返回浏览器。 运行在浏览器上的Javascript,...
JavaScript 执行过程耗时越久,浏览器等待响应用户输入的时间就越长。浏览器在下载和执行脚本时出现阻塞的原因在于,脚本可能会改变页面或 JavaScript 的命名空间,它们对后面页面内容造成影响。一个典型的例子就是...
48.在老的浏览器中不执行此JS:<!-- //--> 49.引用一个文件式的JS:<script type="text/javascript" src="aaa.js"> 50.指定在不支持脚本的浏览器显示的HTML:<noscript></noscript> 51.当超链和ONCLICK事件都有时,则老...
在这个文件中,我们将讨论如何在IE和Chrome浏览器下使新浪微博v6恢复原版。下面是详细的操作步骤: 首先,打开浏览器(IE和Chrome都可用),然后进入新浪微博主页。在这个页面中,按下F12键呼出控制台。控制台是一...
JavaScript事件串连执行多个处理过程的方法 在JavaScript事件处理机制中,通常我们使用`object.event = handler;`的方式初始化事件处理过程。但是,这种方式只能一个事件对应一个事件处理过程。如果希望一个事件...
虽然现代浏览器可以并行的下载JavaScript(部分浏览器),但考虑到JavaScript的依赖关系,他们的执行依然是按照引入顺序进行的。 为了更好的测试这个过程,我写了一个简单的HTTP处理程序页面 service.ashx,它可以...