内容均摘自JavaScript高级程序设计第四版,仅用于记录学习过程。
第二章 HTML中的JavaScript
- 一. <script>元素
- 2.1 <script>元素
- 2.1.1 标签位置
- 2.1.2 推迟执行脚本
- 2.1.3 异步执行脚本
- 2.1.4 动态加载脚本
- 二.行内代码与外部文件
- 2.2 行内代码与外部文件
- 三.文档模式
- 2.3 文档模式
- 四. <noscript>元素
- 2.4 <noscript>元素
- 五.小结
一. <script>元素
2.1 <script>元素
将javascript插入HTML的主要方法是使用<script>
元素。script
有下列8个属性:
type
:代码块中脚本语言的内容类型(MIME类型)- 如果值为
module
,则代码会被当成ES6模块,只有这个时候代码中才能出现import和export关键字
- 如果值为
src
:包含要执行的代码的外部文件的URLcharset
:在外部脚本文件中使用的字符编码- 与src一起使用,告诉浏览器用来编码这个 javascript 程序的字符集
crossorigin
:配置相关请求的CORS(跨源资源共享)设置- 默认不使用CORS
crossorigin= "anonymous"
配置文件请求不必设置凭据标志crossorigin="use-credentials"
设置凭据标志,出站请求会包含凭据- 注释:CORS允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制
integrity
:验证子资源完整性(SRI)- 比对接收到的资源和指定的加密签名
- 如果不匹配,系统报错,脚本不会执行
- 确保内容分发网络(CDN)不会提供恶意内容
- 比对接收到的资源和指定的加密签名
async
:表示立即开始下载脚本,但不能阻止其他页面动作,比如下载资源。- 一旦脚本可用,则会异步执行
- 仅适用于外部脚本
defer
:表示脚本是否延迟到文档完全被解析和显示之后再执行- 仅适用于外部脚本
language:已废弃
使用<script>
的方式有两种:
- 1.直接在网页中嵌入JavaScript代码
<script>
function sayHi() {
console.log("Hi");
}
</script>
在<script>元素中的代码被计算完成之前,页面的其余内容不会加载显示。
⚠️:代码中出现字符串<script>时,应用转义字符"\"
// wrong
<script>
function sayScript() {
console.log("</script>");
}
</script>
// right
<script>
function sayScript() {
console.log("<\/script>");
}
</script>
- 2.在网页中包含外部JavaScript文件
- 使用src属性,其值是一个URL,指向包含JavaScript代码的文件
<script src="example.js"></script>
// 在XHTML文档中,可以忽略结束标签
// 但不可在HTML文件中用,因为它是无效的HTML
// IE不可正常处理
<script src="example.js"/>
⚠️:外部JavaScript文件的扩展名.js不是必需的,浏览器不会检查所包含JavaScript文件的扩展名,这为使用服务端脚本语言动态生成js代码,或在浏览器中将js扩展语言(如TypeScript)转译为js提供了可能性。但服务器经常根据文件扩展名来确定响应的正确MIME类型。
<script>
元素的一个最强大、也备受争议的特性是它可以包含来自外部域的JavaScript文件
<script>
的src属性可以是一个完整的URL,而且这个URL指向的资源可以和包含它的HTML页面不在一个域中,比如:
<script src="http://www.somewhere.com/afile.js"></script>
- 浏览器解析这个资源时,会向该指定路径发送GET请求,以取得相应资源。
- 这个初始请求不受浏览器同源策略限制,但返回并被执行的JavaScript则受限制。
- 来自外部域的代码会被当成加载它页面的一部分来加载和解释,这使我们可以通过不同域分发JavaScript
⚠️:在包含外部域的JavaScript文件时,要确保该域是自己所有的/该域是可信来源。<script>
的integrity
属性可以在引用放在别人服务器上的JavaScript文件,防止其替换掉该文件。
注意:
在没有使用defer属性和async属性时,浏览器会按照<script>
在页面中出现顺序依次解释。
2.1.1 标签位置
现代 Web应用程序通常将所有JavaScript 引用放在<body>
元素中的页面内容后面
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
</head>
<body>
<!-- 这里是页面内容 -->
// 放在页面内容后
<script src="example1.js"></script>
<script src="example2.js"></script>
</body>
</html>
页面在浏览器解析到<body>
的起始标签时开始渲染,过去所有JavaScript文件引用放在<head>
里,意味着必须把所有JavaScript代码都解析完成之后才会渲染页面。
2.1.2 推迟执行脚本
defer
属性:表示脚本在执行的时候不会改变页面的结构,也就是说,脚本会被延迟到整个页面都解析完毕后在执行。
因此设置defer
属性相当于告诉浏览器立即下载,但延迟执行。
<!DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script defer src="example1.js"</script>
<script defer src="example2.js"</script>
</head>
<body>
<!-- 这里是页面内容 -->
</body>
</html>
虽然此例中<script>
元素包含在页面的head
中,但它们会在浏览器解析到</html>
标签后才会执行。
⚠️:
- 实际中推迟执行的脚本的执行顺序不一定,因此最好只包含一个这样的脚本。
defer
属性只对外部脚本文件才有效,行内脚本的defer
属性会被忽略。- 对于XHTML文档,应写成
defer = "defer"
2.1.3 异步执行脚本
async
属性:与defer
属性类似。都只适用于外部脚本,都会告诉浏览器立即开始下载- 与
defer
不同的是,标记为async
的脚本并不保证能按照它们出现的次序执行。 - 添加
async
属性的目的是告诉浏览器,不必等脚本下载和执行完再加载页面,也不必等该异步脚本下载和执行后再加载其他脚本。加载文档元素与脚本的加载与执行并行进行(异步)。
2.1.4 动态加载脚本
可以不使用<script>
标签,通过DOM API向DOM中动态添加script元素同样可以加载指定脚本。
let script = document.createElement("script");
script.src = 'example.js';
document.head.appendChild(script);
默认情况下,以这种方式创建的<script>
是以异步方式加载的,相当于添加了async
属性。
⚠️:不是所有浏览器都支持async
属性。
因此,如果要统一动态脚本的加载行为,可以明确将其设置为同步加载:
let script = document.createElement("script");
script.src = 'example.js';
// 设置为同步加载
script.async = false;
document.head.appendChild(script);
⚠️:这种方式获得的资源对浏览器预加载器不可见,想让预加载器知道这些动态请求文件的存在,可以在文档头部显式声明它们:
<link rel="preload" href="example.js">
二.行内代码与外部文件
2.2 行内代码与外部文件
推荐使用外部文件的理由如下
- 可维护性
- 用一个目录保存所有JavaScript文件,更容易维护。
- 缓存
- 浏览器会根据特定设置缓存所有外部链接的JavaScript文件,如果两个页面都用到同一文件,则该文件只需下载一次。
- 适应未来
- 不必考虑XHTML的问题,包含外部JavaScript文件的语法在HTML和XHTML中是一样的。
三.文档模式
2.3 文档模式
- IE5.5发明了文档模式的概念,即可以使用doctype切换文档模式。最初的文档模式有两种:混杂模式(支持一些非标准的特性)和标准模式(让ie具有兼容标准的行为)。
- 又出现了第三种文档模式:准标准模式,这种模式下的浏览器没有标准模式规定的那么严格。主要区别在于如何对待图片元素周围的空白。
- 混杂模式在所有浏览器中都以省略文档开头的doctype声明作为开关,这不合理,混杂模式在不同浏览器中的差异非常大。
- 准标准模式与标准模式非常接近,很少需要区分。人们说到“标准模式”时,可能指其中一种,对文档模式的检测也不会区分它们。
四. <noscript>元素
2.4 <noscript>元素
<noscript>
元素被用于给不支持JavaScript的浏览器提供替代内容。- 对于禁用JavaScript的浏览器来说,这个元素尤其用处。
<noscript>
元素中可包含任何可以出现在<body>
中的,除了<script>
- 在下列两种情况下,浏览器将显示包含在
<noscript>
中的内容:- 浏览器不支持脚本
- 浏览器对脚本的支持被关闭
任何一个条件满足,<noscript>
中内容就会被渲染,否则不会。
下面是例子:
<body>
<noscript>
<p>This page requires a JavaScript- enabled browser.</p>
</noscript>
</body>
此例在脚本不可用时,让浏览器显示一段话。如果浏览器支持脚本,则用户不会看见这段话。
五.小结
本文重点:
- 要包含外部JavaScript文件,要将src属性设置为要包含文件的URL。文件可以跟网页位于完全不同的域。
- 在不使用
async
和defer
属性的情况下,包含在<script>
中的代码必需严格按次序被解释。 - 通常应把
<script>
元素放到页面末尾,介于主内容之后与</body>
标签之前。 - 可以使用
defer
属性把脚本推迟到文档渲染完在执行,推迟的脚本原则上按照它们被列出的次序执行。 - 可以使用
async
属性表示脚本不需要等待其他脚本,同时异步加载文档(不阻塞文档渲染),异步脚本不能保证按照它们在页面上出现的次序执行。 - 使用
<noscript>
元素可以指定在浏览器不支持脚本时显示的内容,如果浏览器支持并使用脚本,则其内容不会被渲染。