在刚学习Javascript时曾对该问题在小组内做个一次StudyReport,发现其中的基础还是值得分析的。

从标题分析,可以加个Javascript的加载和执行分为两个阶段:加载、执行。而加载即浏览器下载JS脚本的过程,执行时浏览器JS引擎解释执行的过程。

接下来先分析JS脚本加载的过程,加载方式可分为同步加载和异步加载。

同步加载即浏览器加载JS过程中停止对HTML元素的解析,保证JS执行的安全一致性,但如果JS中包含大量计算时,会导致阻塞页面的渲染。常见的JS加载是通过<script>标签置于<head>内加载,这种方式会导致加载时阻塞对HTML元素的渲染,导致页面短暂空白。因此,建议将<script>便签置于</body>前,可以在HTML渲染完成后加载JS文件。即,

传统加载方式:

<head>
<script src='yourscript.js'></script>
</head>
<body></body>

推荐加载方式:

<head></head>
<body>
...
<script src='yourscript.js'>
</script>
</body>

使用一个例子加上一张序列图来描述HTML加载JS/CSS的流程,其中各个步骤均是同步的,会阻塞下一步解析。

<html>
<head>
<link></link>
<script><script>
</head>
<body>
<div></div>
<script></script>
</body>
</html>

  

异步加载也称动态加载,即在后期动态加载JS。常见的动态JS加载有以下几种方式。

1.document.write('yourscript.js');//这种方式在各浏览器行为不一致

2.动态修改<script></script>的src

3.动态插入<script>标签,可在<script>脚本中,也可在onload中

<script>
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = 'yourscript.js';
var x = document.getElementsByTagName('script')[0];
x.parentNode.insertBefore(s, x);
</script>

4.XHR结合eval

var xhr = new XmlHttpRequest();
xhr.onreadstatechange = function(){
if(xhr.readyState==4)
{
if(xhr.status==200)
{
eval(xhr.responseText);
}
}
}
xhr.open("GET",yourscript.js',true);
xhr.send(null);

5.defer和async属性。

<script src='yourscript.js' async/defer ></script>

二者都在onload之前执行完成,可用于不修改DOM的JS脚本加载。不同之处在与,defer下载的JS按顺序执行,而async不能保证执行顺序。

接下来分析脚本的执行流程。执行可分为解释与执行两个过程。

在脚本解释的过程中,会对var和function做不同的处理,var定义的对象赋值undefined,而function定义的对象赋值为函数体。

我们用示例来解释上面的意思。首先看解释器对var的处理。

<script>
alert(i); // undefined
var i = 1;
alert(i);
</script>

上述代码在解释器中进行转换为:

<script>
var i;
alert(i); // undefined
i = 1;
alert(i);
</script>

这样就能理解为什么i值为undefinded。接下来我们看看对function的处理。

<script>
alert(func); // function(){alert('out')}
var func = function(){
alert('out');
};
alert(func);
</script>

上述代码在解释器中进行转换为:  

<script>
var func = function(){
alert('out');
};
alert(func); // function(){alert('out')}
alert(func);
</script>

这就是解释器对var和function的不同处理,function的声明和函数体定义都会被提前。

另外,脚本解释过程中,以<script>以块为单位执行,块间可共享变量。对外部脚本会将JS加载完成并执行,而且JS脚本在执行的过程中会阻塞后续HTML页面的渲染。

<script>
alert(i); // error 该块内后续代码不执行
i = 1;
alert(i);
</script>
<script>
var j=0;
alert(j); //
</script>

上面这个例子解释了脚本以块为单位执行的原理,虽然第一个<script>会报异常,但并不影响第二个<script>的执行。

<script>
var i = 1;
alert(i); //1
</script>
<script>
alert(i); //1
</script>

通过上例结果,可解释两个<script>之间是可以共享变量的。这也就是为什么加载jquery.min.js后,在任何<script>中都可以使用$来引用jQuery。 

关于浏览器加载JS并执行的过程暂时描述到此,后期继续补充。

浏览器中Javascript的加载和执行的更多相关文章

  1. 浏览器环境下Javascript脚本加载与执行探析之DOMContentLoaded

    在”浏览器环境下Javascript脚本加载与执行探析“系列文章的前几篇,分别针对浏览器环境下JavaScript加载与执行相关的知识点或者属性进行了探究,感兴趣的同学可以先行阅读前几篇文章,了解相关 ...

  2. 浏览器环境下JavaScript脚本加载与执行探析之动态脚本与Ajax脚本注入

    在<浏览器环境下JavaScript脚本加载与执行探析之defer与async特性>中,我们研究了延迟脚本(defer)和异步脚本(async)的执行时机.浏览器支持情况.浏览器bug以及 ...

  3. 浏览器环境下JavaScript脚本加载与执行探析之defer与async特性

    defer和async特性相信是很多JavaScript开发者"熟悉而又不熟悉"的两个特性,从字面上来看,二者的功能很好理解,分别是"延迟脚本"和"异 ...

  4. 前端性能优化:细说JavaScript的加载与执行

    本文主要是从性能优化的角度来探讨JavaScript在加载与执行过程中的优化思路与实践方法,既是细说,文中在涉及原理性的地方,不免会多说几句,还望各位读者保持耐心,仔细理解,请相信,您的耐心付出一定会 ...

  5. 浏览器环境下JavaScript脚本加载与执行探析之代码执行顺序

    本文主要基于向HTML页面引入JavaScript的几种方式,分析HTML中JavaScript脚本的执行顺序问题 1. 关于JavaScript脚本执行的阻塞性 JavaScript在浏览器中被解析 ...

  6. 高性能JavaScript(加载和执行)

    当浏览器遇到 <script> 标签时,它是没办法知道 JavaScript 是否会向DOM中添加内容或引入其他元素,甚至关闭某一个标签.因此这个时候浏览器就会停止处理页面,先执行Java ...

  7. 如何加快JavaScript的加载与执行

    JS 有个很无语的阻塞特性,就是当浏览器在执行JS 代码时,不能同时做其他任何事情,无论其代码是内嵌的还是外部的. 浏览器在碰到一个引入外部JS 文件的<script>标签时会停下所有工作 ...

  8. 高性能JavaScript之加载和执行

    JS在浏览器中的性能,可以认为是开发者所面临的最重要的可行性问题.这个问题因JS的阻塞特性变得复杂,也就是说当浏览器在执行JS代码时,不能同时做其他任何事情.事实上,大多数浏览器都使用单一进程来处理U ...

  9. IE浏览器中IFrame被加载两次问题的解决-sunziren

    本文为作者sunziren原创,首发博客园,转载请注明出处. 昨天遇到了一个问题,先上代码. var content = '<iframe src="www.baidu.com&quo ...

随机推荐

  1. 转 : 用Delphi编写安装程序

    http://www.okbase.net/doc/details/931  还没有亲自验证过,仅收藏 当你完成一个应用软件的开发后,那么你还需要为该软件做一个规范化的安装程序,这是程序设计的最后一步 ...

  2. 泛型容器单元(Generics.Collections)[2]: TQueue<T> 队列列表

    TQueue 和 TStack, 一个是队列列表, 一个是堆栈列表; 一个是先进先出, 一个是先进后出. TQueue 主要有三个方法.一个属性:Enqueue(入列).Dequeue(出列).Pee ...

  3. MyEclipse代码自动补全设置

    1.打开 Eclipse  -> Window -> Perferences -> Java -> Editor -> Content Assist,在右边最下面一栏找到 ...

  4. HTML5属性运用

    HTML5 接触移动端,或专注于支持HTML5浏览器进行前端开发的工作者都不会陌生,这个已经普及很广,对于我专注于PC端开发的人来说,觉得陌生但又觉得很熟悉,大家都知道做PC前端开发为了兼容IE老版本 ...

  5. Dependency Properties

      Introduction Value resolution strategy The magic behind it How to create a DepdencyProperty Readon ...

  6. Ubuntu 16.04 LTS 安装R及RStudio Server

    1.R的安装 1.1首先添加镜像源 # Ctrl+Alt+T打开终端 $ sudo gedit /etc/apt/sources.list # 加入新镜像源 回车之后会自动跳出一个文本框,然后在相似的 ...

  7. 【原】iOS学习18之OC内存管理高级

    1.属性的内存管理 1> 属性的语义特性 2> assign下的属性内部实现 @property (nonatomic, assign) NSString *name; @synthesi ...

  8. BZOJ4707 : B君的技巧

    建立线段树,设$f[x][l][r]$表示当前考虑$x$点,最左端是$l$,最右端是$r$的最少代价. 如果$a$在$x<<1$,$d$在$x<<1|1$, 设$g[a][c] ...

  9. mysql case then使用

    表的创建CREATE TABLE `lee` (`id` int(10) NOT NULL AUTO_INCREMENT, `name` char(20) DEFAULT NULL, `birthda ...

  10. WPF standard ComboBox Items Source Change Issue

    Today I encountered an issue with the WPF standard CombBox where if the bound ItemsSource (collectio ...