- 外部引入js脚本的优点:
1) 可以把大块的Js代码从html文件中删除,这有助于保持内容和行为的分离,从而简化html文件。
2) 如果多个Web页面公用相同的JavaScript代码,用src属性可以让你只管理一份代码,而不用在代码改变时编辑每个html文件
3) 如果一个JavaScript代码文件由多个页面共享,就只需要下载它一次,通过使用它的第一个页面——随后的页面可以从浏览器缓存检索它
4) 由于src属性的值可以使任意的url,因此来自一个Web服务器的JavaScript程序或Web页面可以使用由另一个Web服务器输出的代码。
5) 从其他网站载入脚本的能力,可以让我们更好地利用缓存。Google正在为通用的客户端类库推广标准且好记的url,可以让浏览器只缓冲一份副本,并且网络上的任意站点都可以使用。链接JavaScript代码到Google服务器,可以减少Web页面的启动时间,因为这些类库可能已经存在于用户的浏览器缓存中,但你必须相信第三方提供的代码服务,这对于你的站点来说很关键。
2.url中的JavaScript:
在URL后面跟一个javascript:协议限定符,是一种嵌入JavaScript代码到客户端的方式.这种特殊的协议类型指定URL内容为任意字符串.这个字符串是会被JavaScript解释器运行的JavaScript代码.它被当做单独的一行代码对待,这意味着语句之间必须用分号隔开,而//注释必须用/**/注释代替。javascript:URL能识别的“资源”是转换成字符串执行代码的返回值。如果代码返回undefined,那么这个资源是没有内容的。
javascript:URL可以用在可以使用常规URL的任意地方:比如<a>标记href属性,<form>的action属性,甚至window.open()方法的参数。超练级里的javascriptURL可以是这样:<a href=”javascript:alert(new Date().toLocaleTimeString());” >检查时间,而不必覆盖整个文档</a>
当浏览器载入这种类型的URL时,它会执行JavaScript代码,但是由于没有返回值(alert()返回undefined)作为新文档的显示内容,类似FireFox的浏览器并不会替换当前的文档。(在这种情况下,JavaScript:URL和onclick事件处理程序的目的一样。上面的链接通过<button>元素的onclick处理程序来表示会更好,因为<a>元素通常应该保留为超链接,用来载入新文档。)-如果要确保javascript:URL不会覆盖当前文档,可以用void操作符强制函数调用或给表达式赋予undefined值。
<a href=”javascript:void window.open(‘about:blank’);”>打开一个窗口</a>
如果这个url里没有void操作符,调用window.open()方法返回的值会(在一些浏览器里)被转化为字符串并显示,而当文档也会被覆盖为包含该字符串的文档:
[object Windwo]
和html事件处理程序一样,javascript url是web早期的遗物,通常应该避免在现代html里使用。但javascript:url在html文档之外确实有着重要的角色。如果要测试一段javascript代码,那么可以再浏览器地址栏里直接输入javascript:url。
3.书签:在Web浏览器中,“书签”就是一个保存起来的url。如果书签是javascript:url,那么保存的就是一小段脚本,叫做bookmarklet。bookmarklet是一个小型程序,很容易就可以从浏览器的菜单或工具栏里启动。bookmarklet里的代码执行起来就像页面上的脚本一样,可以从浏览器的菜单或工具栏里启动。bookmarklet里的代码执行起来就像页面上的脚本一样,可以查询和设置文档的内容、呈现和行为。只要书签不返回值,它就可以操作当前显示的任何文档,而不把文档替换成新的内容。
考虑下面<a>标签里的javascript:url。单击连接会打开一个简单的javascript表达式计算器,它允许在页面环境中计算表达式和执行语句:
注意,即使这个javascript url是写成多行的,html解析器仍将它作为单独的一行对待,并且其中单行//注释也是无效的。还有,要记住代码是单引号的html属性的一部分,所以代码不可以包含任何单引号。
在开发时,把这样的链接硬编码在页面中是有用的;而把它另存为可以在任何页面上运行的书签,就更有用了。通常,在浏览器里把超链接的地址加入书签可以这样做,在链接上右击选择类似“Bookmark Link”的选项,或者拖动链接到书签工具栏。
4.如果web页面包含一个嵌入的窗体(通常使用<iframe>元素),嵌入文档中的Javascript代码和被嵌入文档里的Javascript代码会有不同的全局对象,它可以当做一个单独的Javascript程序。但是,要记住,没有严格的关于Javascript程序范围的定义。如果外面和里面的文档来自与同一个服务器,那么两个文档的代码就可以进行交互,并且如果你愿意,就可以把它们当做是一个程序的两个相互作用的部分。
5.bookmarklet里的Javascript:url存在于文档之外,可以想象成是一种用户扩展或者对于其他程序的修改。当用户执行一个bookmarklet时,书签里的Javascript代码就可以访问全局对象和文档的内容,以及对它们进行操作。
6.javascript程序的执行有两个阶段。在第一阶段,载入文档内容,并执行<script>元素里的代码(包括内联脚本和外部脚本)。脚本通常会按他们在文档里的出现顺序执行。通常所有脚本里的Javascript代码都是从上往下,按照它在条件,循环以及其他控制语句中的出现顺序执行。
当文档载入完成,并且所有脚本执行完成后,Javascript执行就进入它的第二阶段。这个阶段是异步的,而且是事件驱动的。在事件驱动阶段,Web浏览器调用事件处理程序函数(由第一阶段里执行的脚本指定的html事件处理程序,或之前的事件处理程序来定义),来响应异步发生的事件。调用事件处理程序通常是响应用户输入(如鼠标单击,键盘按下等)。但是,还可以由网络活动,运行时间或者Javascript代码中的错误来触发。嵌入Web页面里的Javascript:url也可以被当成是一种事件处理程序,因为直到用户通过单击链接或提交表单来激活之后他们才会有效果。
事件驱动阶段里发生的第一个事件是load事件,指示文档已经完全载入,并且可以操作。Javascript程序经常用这个事件来触发或发送消息。我们经常看到一些函数的脚本程序,除了定义一个onload事件处理函数外不做其他操作,这个函数会在脚本事件驱动阶段开始时被onload事件触发。正是这个onload事件会对文档进行操作,并做程序想做的任何事。Javascript程序载入阶段是相对短暂的,通常只持续1-2秒,在文档载入完成之后,只要Web浏览器显示文档,事件驱动阶段就会一直持续下去。因为这个阶段是异步的和事件驱动的,所以可能有长时间处于不活动状态。没有Javascript被执行。被用户或网络事件触发的活动打断。
核心Javascript和客户端Javascript都有一个单线程执行模型。脚本和事件处理程序(无论如何)在同一个时间只能执行一个,没有并发性。这保持了Javascript编程的简单性。
7.当html解析器遇到<script>元素时,它默认必须先执行脚本,然后再恢复文档的解析和渲染。这对于内联脚本没什么问题,但如果脚本源码是一个由src属性指定的外部文件,这意味着脚本后面的文档部分在下载和执行脚本之前都不会出现在浏览器中。(至文档的文本内容已经载入,但是未被浏览器引擎解析为DOM树,而DOM树的生成是受Javascript代码影响的,Javascript代码会“阻塞”页面UI的渲染。
8.脚本的执行只是在默认情况下是同步和阻塞的。<script>标签可以有defer和async属性,这(在支持他们的浏览器里)可以改变脚本的执行方法。这些都是布尔属性,没有值;只需要出现在<script>标签里即可。html5说这些属性只在和src属性联合使用时才有效,但有些浏览器还支持延迟的内联脚本。
<script defersrc="deferred.js" ></script>
<script async src="async.js"></script>
defer和async属性都像在告诉浏览器链接进来的脚本不会使用document.write(),也不会生成文档内容,因此浏览器可以再下载脚本时继续解析和渲染文档。defer属性使得浏览器延迟脚本的执行,直到文档的载入和解析完成,并可以操作。async属性使得浏览器可以尽快地执行脚本,而不用在下载脚本时阻塞文档解析。如果<script>标签同时有两个属性,同时支持两者的浏览器会遵从async属性并忽略defer属性。注意,延迟的脚本会按他们在文档里的出现顺序执行。而异步脚本在他们在他们载入后执行,这意味着他们可能会无序执行。
9.按照约定,事件处理程序的属性的名字是以“on”开始,后面跟着时间的名字。还要注意在上面的任何代码里没有函数调用:只是把函数本身赋值给这些属性。浏览器会在事件发生时执行调用。用时间进行一步编程会经常涉及嵌套函数,也经常要在函数里定义函数。