在刚学习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. poj2109

    刚开始看着道题时,感觉不用高精度好像就没法做,想了半天然后果断去看依然博客(这样确实不好),发现又用到了double(这个可以放“+” “-” 300多位的家伙!!!) #include <io ...

  2. ASP.NET 操作Cookie详解 增加,修改,删除

    Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份而储存在用户本地终端上的数据(通常经过加密).定义于RFC2109.它是网景公司的前雇员Lou Montulli在1993年3 ...

  3. 连连看[HDU1175]

    连连看 Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submi ...

  4. BZOJ4449 : [Neerc2015]Distance on Triangulation

    首先拓扑,每次取出度数为$2$的点,这样可以把所有三角形都找到. 那么建出对偶图,会发现是一棵树. 对这棵树进行点分治,每次取出重心,DFS求出所有在里面的点,然后从重心$3$个点分别做一次BFS. ...

  5. ACM: HDU 5285 wyh2000 and pupil-二分图判定

     HDU 5285  wyh2000 and pupil Time Limit:1500MS     Memory Limit:65536KB     64bit IO Format:%I64d &a ...

  6. Jquery-UI实现弹出框样式

    需要引用 <link href="CSS/jquery-ui.custom.min.css" rel="stylesheet" /> <scr ...

  7. [ACM训练] DEV C++如何处理不能调试

    复试上机一定要用DEV C++,使用不熟练,出现一些问题,记录如下: 1.DEV C++ 不能调试 (1)tools->compiler option->settings:linker里设 ...

  8. [WP8.1UI控件编程]SemanticZoom控件实现分组列表

    11.1.5 SemanticZoom实现分组列表 SemanticZoom控件可以让用户实现一种更加高级的列表,这种列表可以对列表的项目进行分组,同时这个SemanticZoom控件会提供两个具有相 ...

  9. 百度mobile UI组件GMU demo学习1-结构和初始化

    移动web现在已经是zepto的天下,但是一直找不到合适UI库,找了一段时间,终于找到了百度的ui库gum和inter 的 appframework UI库 相比之下,百度的UI库更接地气,配合百度强 ...

  10. 【BZOJ】1105: [POI2007]石头花园SKA

    题意 二维平面上有\(n(2 \le n \le 1000000)\)个点,可以花费\(w_i\)交换第\(i\)个点的横纵坐标.求在满足能覆盖所有点的最小矩阵周长最短的情况下花费最小. 分析 这题太 ...