在刚学习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. 停靠技术 Dock

    C:\Program Files\Borland\Delphi7\Demos\Docking   delphi例子 网上文档 http://www.docin.com/p-95543759.html

  2. Sleep函数的真正用意

    转自:http://blog.csdn.net/boyuejiang/article/details/8908333 关于VOID Sleep(DWORD dwMilliseconds);函数,许多人 ...

  3. mybatis做like模糊查询

    http://www.cnblogs.com/cyttina/p/3894428.html

  4. 微信客户端自带的Js Api:WeixinJSBridge

    <!DOCTYPE html> <html> <head> <title>微信WeixinJSBridge API</title> < ...

  5. The Result of an Interesting and Useful Program on Floating Numbers

    The program: class Program { static void Main() { const double infinity = double.PositiveInfinity; c ...

  6. Mac下android_sdk配置环境变量

    1.启动Terminal终端工具 2.输入cd ~/ 进入当前用户的home目录 3. 创建: touch .bash_profile 4.打开并编辑: open .bash_profile 5.在文 ...

  7. Android js相互调用

    一.webview相当于android中的浏览器,基于webkit开发,可以浏览网页文件,支持css javas cript 以及html webview.getSettings().setJavaS ...

  8. 洛谷 P2661 信息传递 Label:并查集||强联通分量

    题目描述 有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学. 游戏开始时,每人都只知道自己的生日.之后每一 ...

  9. 【BZOJ】1998: [Hnoi2010]Fsk物品调度

    http://www.lydsy.com/JudgeOnline/problem.php?id=1998 题意: 给你6个整数$n,s,q,p,m,d$. 有$n$个位置和$n-1$个盒子,位置编号从 ...

  10. java enum(枚举)使用详解 + 总结

    enum 的全称为 enumeration, 是 JDK 1.5  中引入的新特性,存放在 java.lang 包中. 下面是我在使用 enum 过程中的一些经验和总结,主要包括如下内容: 1. 原始 ...