详解Javascript 装载和执行_基础知识
首先,我想说一下Javascript的装载和执行。通常来说,浏览器对于Javascript的运行有两大特性:1)载入后马上执行,2)执行时会阻塞页面后续的内容(包括页面的渲染、其它资源的下载)。于是,如果有多个js文件被引入,那么对于浏览器来说,这些js文件被被串行地载入,并依次执行。
因为javascript可能会来操作HTML文档的DOM树,所以,浏览器一般都不会像并行下载css文件并行下载js文件,因为这是js文件的特殊性造成的。所以,如果你的javascript想操作后面的DOM元素,基本上来说,浏览器都会报错说对象找不到。因为Javascript执行时,后面的HTML被阻塞住了,DOM树时还没有后面的DOM结点。所以程序也就报错了。
传统的方式
所以,当你写在代码中写下如下的代码:
基本上来说,head里的 <script>标签会阻塞后续资源的载入以及整个页面的生成。我专门做了一个示例你可以看看:示例一。 注意:我的alert.js中只有一句话:alert(“hello world”) ,这更容易让你看到javascript是怎么阻塞后面的东西的。</p>
<p>所以,你知道为什么有很多网站把javascript放在网页的最后面了,要么就是动用了window.onload或是docmuemt ready之类的事件。</p>
<p>另外,因为绝大多数的Javascript代码并不需要等页面,所以,我们异步载入的功能。那么我们怎么异步载入呢?</p>
<p>document.write方式</p>
<p>于是,你可能以为document.write()这种方式能够解决不阻塞的方式。你当然会觉得,document.write了的<script>标签后就可以执行后面的东西去了,这没错。对于在同一个script标签里的Javascript的代码来说,是这样的,但是对于整个页面来说,这个还是会阻塞。 下面是一段测试代码:</p>
<p></p>
<div class="codetitle">
<span><a style="CURSOR: pointer" data="35700" class="copybut" id="copybut35700" onclick="doCopy('code35700')"><u>复制代码</u></a></span> 代码如下:</div>
<div class="codebody" id="code35700">
<br>
<script type="text/javascript" language="javascript"><br>
function loadjs(script_filename) {<br>
document.write('<' 'script language="javascript" type="text/javascript"');<br />
document.write(' src="' script_filename '">');<br>
document.write('<' '/script' '>');<br>
alert("loadjs() exit...");<br>
}<br>
var script = 'http://coolshell.cn/asyncjs/alert.js';<br>
loadjs(script);<br>
alert("loadjs() finished!");<br>
</script>
你觉得alert的顺序是什么?你可以在不同的浏览器里试一试。这里的想关的测试页面:示例二。
script的defer和async属性
IE自从IE6就支持defer标签,如:
对于IE来说,这个标签会让IE并行下载js文件,并且把其执行hold到了整个DOM装载完毕(DOMContentLoaded),多个defer的<script>在执行时也会按照其出现的顺序来运行。最重要的是<script>被加上defer后,其不会阻塞后续DOM的的渲染。但是因为这个defer只是IE专用,所以一般用得比较少。</p>
<p>而我们标准的的HTML5也加入了一个异步载入javascript的属性:async,无论你对它赋什么样的值,只要它出现,它就开始异步加载js文件。但是, async的异步加载会有一个比较严重的问题,那就是它忠实地践行着“载入后马上执行”这条军规,所以,虽然它并不阻塞页面的渲染,但是你也无法控制他执行的次序和时机。你可以看看这个示例去感受一下。</p>
<p>支持 async标签的浏览器是:Firefox3.6 ,Chrome 8.0 ,Safari 5.0 ,IE 10 ,Opera还不支持(来自这里)所以这个方法也不是太好。因为并不是所有的浏览器你都能行。</p>
<p>动态创建DOM方式</p>
<p>这种方式可能是用得最多的了。</p>
<p></p>
<div class="codetitle">
<span><a style="CURSOR: pointer" data="53194" class="copybut" id="copybut53194" onclick="doCopy('code53194')"><u>复制代码</u></a></span> 代码如下:</div>
<div class="codebody" id="code53194">
<br>
function loadjs(script_filename) {<br>
var script = document.createElement('script');<br>
script.setAttribute('type', 'text/javascript');<br>
script.setAttribute('src', script_filename);<br>
script.setAttribute('id', 'coolshell_script_id');<br>
<br>
script_id = document.getElementById('coolshell_script_id');<br>
if(script_id){<br>
document.getElementsByTagName('head')[0].removeChild(script_id);<br>
}<br>
document.getElementsByTagName('head')[0].appendChild(script);<br>
}<br>
<br>
var script = 'http://coolshell.cn/asyncjs/alert.js';<br>
loadjs(script);<br>
</div>
<p>这个方式几乎成了标准的异步载入js文件的方式,这个方式的演示请参看:示例三。这方式还被玩出了JSONP的东东,也就是我可以为script的src指定某个后台的脚本(如PHP),而这个PHP返回一个javascript函数,其参数是一个json的字符串,返回来调用我们的预先定义好的javascript的函数。你可以看一下这个示例:t.js (这个示例是我之前在微博征集的一个异步ajax调用的小例子)</p>
<p>按需异步载入js</p>
<p>上面那个DOM方式的例子解决了异步载入Javascript的问题,但是没有解决我们想让他按我们指定的时机运行的问题。所以,我们只需要把上面那个DOM方式绑到某个事件上来就可以了。</p>
<p>比如:</p>
<p>绑在window.load事件上——示例四</p>
<p>你一定要比较一下示例四和示例三在执行上有什么不同,我在这两个示例中都专门用了个代码高亮的javascript,看看那个代码高亮的的脚本的执行和我的alert.js的执行的情况,你就知道不同了)</p>
<p></p>
<div class="codetitle">
<span><a style="CURSOR: pointer" data="34632" class="copybut" id="copybut34632" onclick="doCopy('code34632')"><u>复制代码</u></a></span> 代码如下:</div>
<div class="codebody" id="code34632">
<br>
window.load = loadjs("<a href="http://coolshell.cn/asyncjs/alert.js">http://coolshell.cn/asyncjs/alert.js</a>")<br>
</div>
<p>绑在特定的事件上——示例五</p>
<p></p>
<div class="codetitle">
<span><a style="CURSOR: pointer" data="16878" class="copybut" id="copybut16878" onclick="doCopy('code16878')"><u>复制代码</u></a></span> 代码如下:</div>
<div class="codebody" id="code16878">
<br>
<p style="cursor: pointer" onclick="LoadJS()">Click to load alert.js </p><br>
</div>
<p>这个示例很简单了。当你点击某个DOM元素,才会真正载入我们的alert.js。</p>
<p>更多</p>
<p>但是,绑定在某个特定事件上这个事似乎又过了一点,因为只有在点击的时候才会去真正的下载js,这又会太慢了了。好了,到这里,要抛出我们的终极问题——我们想要异步地把js文件下载到用户的本地,但是不执行,仅当在我们想要执行的时候去执行。</p>
<p>要是我们有下面这样的方式就好了:</p>
<p></p>
<div class="codetitle">
<span><a style="CURSOR: pointer" data="43581" class="copybut" id="copybut43581" onclick="doCopy('code43581')"><u>复制代码</u></a></span> 代码如下:</div>
<div class="codebody" id="code43581">
<br>
var script = document.createElement("script");<br>
script.noexecute = true;<br>
script.src = "alert.js";<br>
document.body.appendChild(script);<br>
<br>
//后面我们可以这么干<br>
script.execute();<br>
</div>
<p>可惜的是,这只是一个美丽的梦想,今天我们的Javascript还比较原始,这个“JS梦”还没有实现呢。</p>
<p>所以,我们的程序员只能使用hack的方式来搞。</p>
<p>有的程序员使用了非标准的script的type来cache javascript。如:</p>
<p></p>
<div class="codetitle">
<span><a style="CURSOR: pointer" data="63471" class="copybut" id="copybut63471" onclick="doCopy('code63471')"><u>复制代码</u></a></span> 代码如下:</div>
<div class="codebody" id="code63471">
<br>
<script type=cache/script src="./alert.js"></script>
因为”cache/script”,这个东西根本就不能被浏览器解析,所以浏览器也就不能把alert.js当javascript去执行,但是他又要去下载js文件,所以就可以搞定了。可惜的是,webkit严格符从了HTML的标准——对于这种不认识的东西,直接删除,什么也不干。于是,我们的梦又破了。
所以,我们需要再hack一下,就像N多年前玩preload图片那样,我们可以动用object标签(也可以动用iframe标签),于是我们有下面这样的代码:
function cachejs(script_filename){
var cache = document.createElement('object');
cache.data = script_filename;
cache.id = "coolshell_script_cache_id";
cache.width = 0;
cache.height = 0;
document.body.appendChild(cache);
}
然后,我们在的最后调用一下这个函数。请参看一下相关的示例:示例六
在Chrome下按 Ctrl Shit I,切换到network页,你就可以看到下载了alert.js但是没有执行,然后我们再用示例五的方式,因为浏览器端有缓存了,不会再从服务器上下载alert.js了。所以,就能保证执行速度了。
关于这种preload这种东西你应该不会陌生了。你还可以使用Ajax的方式,如:
var xhr = new XMLHttpRequest();
xhr.open('GET', 'new.js');
xhr.send('');
到这里我就不再多说了,也不给示例了,大家可以自己试试去。
最后再提两个js,一个是ControlJS,一个叫HeadJS,专门用来做异步load javascript文件的。
好了,这是所有的内容了,希望大家看过后能对Javascript的载入和执行,以及相关的技术有个了解。同时,也希望各前端高手不吝赐教!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

如何使用WebSocket和JavaScript实现在线语音识别系统引言:随着科技的不断发展,语音识别技术已经成为了人工智能领域的重要组成部分。而基于WebSocket和JavaScript实现的在线语音识别系统,具备了低延迟、实时性和跨平台的特点,成为了一种被广泛应用的解决方案。本文将介绍如何使用WebSocket和JavaScript来实现在线语音识别系

WebSocket与JavaScript:实现实时监控系统的关键技术引言:随着互联网技术的快速发展,实时监控系统在各个领域中得到了广泛的应用。而实现实时监控的关键技术之一就是WebSocket与JavaScript的结合使用。本文将介绍WebSocket与JavaScript在实时监控系统中的应用,并给出代码示例,详细解释其实现原理。一、WebSocket技

如何利用JavaScript和WebSocket实现实时在线点餐系统介绍:随着互联网的普及和技术的进步,越来越多的餐厅开始提供在线点餐服务。为了实现实时在线点餐系统,我们可以利用JavaScript和WebSocket技术。WebSocket是一种基于TCP协议的全双工通信协议,可以实现客户端与服务器的实时双向通信。在实时在线点餐系统中,当用户选择菜品并下单

如何使用WebSocket和JavaScript实现在线预约系统在当今数字化的时代,越来越多的业务和服务都需要提供在线预约功能。而实现一个高效、实时的在线预约系统是至关重要的。本文将介绍如何使用WebSocket和JavaScript来实现一个在线预约系统,并提供具体的代码示例。一、什么是WebSocketWebSocket是一种在单个TCP连接上进行全双工

JavaScript和WebSocket:打造高效的实时天气预报系统引言:如今,天气预报的准确性对于日常生活以及决策制定具有重要意义。随着技术的发展,我们可以通过实时获取天气数据来提供更准确可靠的天气预报。在本文中,我们将学习如何使用JavaScript和WebSocket技术,来构建一个高效的实时天气预报系统。本文将通过具体的代码示例来展示实现的过程。We

JavaScript教程:如何获取HTTP状态码,需要具体代码示例前言:在Web开发中,经常会涉及到与服务器进行数据交互的场景。在与服务器进行通信时,我们经常需要获取返回的HTTP状态码来判断操作是否成功,根据不同的状态码来进行相应的处理。本篇文章将教你如何使用JavaScript获取HTTP状态码,并提供一些实用的代码示例。使用XMLHttpRequest

CIFS,又称作通用Internet文件系统,是SMB(服务器消息块)的一种变体,旨在通过小型局域网(LAN)实现对文件夹、文件和打印机的共享访问。Linux附带了CIFS—Utils包,用于使用CIFS协议通过本地网络装载和管理跨平台文件和打印机。mount.cifs是LinuxCIFS—Utils包的一部分。在本教程中,我将探讨如何使用Linuxmount.cifs实用程序在Linux上装载共享文件夹。请注意,CIFS协议已被SMB2和SMB3协议所取代,这两者更为安全。在Windows系统

用法:在JavaScript中,insertBefore()方法用于在DOM树中插入一个新的节点。这个方法需要两个参数:要插入的新节点和参考节点(即新节点将要被插入的位置的节点)。
