JavaScript高级程序设计(第四版)学习笔记(第二章)

391 阅读4分钟

二、HTML中的JavaScript

2.1 <script>元素

<script>元素有下面8个属性:

  • async:可选。表示应该立即开始下载脚本,但不能阻止其他 页面动作,比如下载资源或等待其他脚本加载。只对外部脚本文件有效;

  • charset:可选。使用src属性指定的代码字符集。这个属性很少使用,因为大多数浏览器不在乎它的值;

  • crossorigin:可选。配置相关请求的CORS(跨源资源共 享)设置。默认不使用CORS;

  • defer:可选。表示在文档解析和显示完成后再执行脚本是没有问题的。只对外部脚本文件有效;

  • integrity:可选。允许比对接收到的资源和指定的加密签名 以验证子资源完整性(SRI,Subresource Intergrity)。如果接收到 的资源的签名与这个属性指定的签名不匹配,则页面会报错,脚 本不会执行。这个属性可以用于确保内容分发网络(CDN, Content Delivery Network)不会提供恶意内容;

  • language:废弃。最初用于表示代码块中的脚本语言;

  • src:可选。表示包含要执行的代码的外部文件;

  • type: 可选。代替language,表示代码块中脚本语言的内容类型(也称MIME类型);

使用<script>的方式有两种:通过它直接在网页中嵌入 JavaScript代码,以及通过它在网页中包含外部JavaScript文件。

要嵌入行内JavaScript代码,直接把代码放在<script>元素中 就行:

<script>
function sayHi(){
console.log("Hi!");
}
</script>

包含在<script>内的代码会被从上到下解释,在<script>元素中的代码被计算完成之前,页面的其余内容不会被加载,也不会被显示。

在使用行内JavaScript代码时,要注意代码中不能出现字符串</script>,因为浏览器解析行内脚本的方式决定了它在看到字符串</script>时,会将其当成结束的</script>标签。

解决方案:需要转义字符反斜杠“\”即可。

要包含外部文件中的JavaScript,就必须使用src属性。这个属性的值是一个URL,指向包含 JavaScript代码的文件,比如:

<script src="example.js"></script>

<script>元素的src属性可以是一个完整的URL,而且这个URL指向的资源可以跟包含它的html页面不在同一个域中:

 <script src="http://www.somewhere.com/afile.js">
 </script> 

浏览器在解析这个资源时,会向 src 属性指定的路径发送一个 GET 请求,以取得相应资源。这个初始的请求不受浏览器同源策略限制,但返回并被执行的JavaScript则受限制。当然,这个请求仍然受父页面HTTP/HTTPS协议的限制。

2.1.1 标签占位符

<script>元素放在页面的<head>标签中,目的:把外部的CSS和JavaScript文件集中到一起;缺点:这意味着必须把JavaScript代码都下载、解析和解释完成后,才能开始渲染页面,在此期间浏览器窗口完全空白。

为解决这个问题,通常把JavaScript引用放在<body>元素中的页面内容后面。

2.1.2 推迟执行脚本

defer:在<script>元素上设置defer属性,告诉浏览器立即下载,但执行延迟。(HTML5中明确规定,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>元素会在浏览器解析到结束的标签后才会执行。

HTML5规范要求脚本应该按照它们出现的顺序执行,第一个推迟的脚本在第二个推迟的脚本之前执行(实际不一定),但两者都会在DOMContentLoaded事件之前执行。

2.1.3 异步执行脚本

async:与defer类似,不同的是标记为async的脚本并不能保证能按照它们出现的次序执行。

给脚本添加async属性是告诉浏览器,不必等脚本下载和执行完后再加载页面,同样也不必等该异步脚本下载和执行后再加载其他脚本。异步脚本不应该在加载期间修改DOM。

异步脚本保证会在页面的load事件前执行,但可能会在DOMContentLoaded之前或之后。

2.1.4 动态加载脚本

JavaScript可以使用DOM API,可以通过向DOM中动态添加script元素来加载指定的脚本。

let script = document.createElement('script');
script.scr ='gibberish.js';
document.head.appendChild(script);

在HTMLElement元素添加到DOM且执行到这段代码前不会发送请求。默认以这种方式创建的<script>元素是以异步方式加载的,相当于添加了async属性。

所有浏览器都支持createElement()方法,但不是所有浏览器都支持async属性,若要统一动态脚本的加载行为,可以明确设置为同步加载:

let script =document.createElement('script');
script.scr ='gibberish.js';
script.async =false;
document.head.appendChild(script);

以这种方式获取的资源对浏览器预加载器是不可见的,会严重影响它们在资源获取队列中的优先级,要想让预加载器知道这些动态请求文件的存在,可以在文档头部显式声明:

<link rel='"preload" href="gibberish.js">

2.1.5 XHTML中的变化

2.1.6 废弃的语法

2.2行内代码与外部文件

推荐使用外部文件的理由:

可维护性: 用一个目录保存所有JavaScript文件更容易维护,开发者可以独立于使用他们的HTML页面来编辑代码。

缓存: 浏览器会根据特定的设置缓存所有外部链接的JavaScript文件,意味着如果两个页面都用到同一个文件,则该文件只需下载一次。

适应未来: 包含外部JavaScript文件的语法在HTML和XHTML中是一样的。

2.3 文档模式

准标准模式与标准模式非常接近,很少需要区分。

2.4 <noscript>元素

<noscript>元素可以包含任何可以出现在<body>中的HTML元素,<script>除外,在下列两种情况下,浏览器将显示包含在<noscript>中的内容:

  • 浏览器不支持脚本;
  • 浏览器对脚本的支持关闭。 任何一个条件满足,包含在<noscript>中的内容会被渲染。

2.5 小结:

JavaScript是通过<script>元素插入到HTML页面中的。

  • 要包含JavaScript文件,必须将scr属性设置为要包含文件的URL。文件可以跟网页在同一台服务器,也可以位于完全不同的域;

  • 所有 <script> 元素会依照它们在网页中出现的次序被解释。在不使用 defer 和 async 属性的情况下,包含在 <script>元素中的代码必须严格按次序解释。

  • 对不推迟执行的脚本,浏览器必须解释完位于 <script> 元素中的代码,然后才能继续渲染页面的剩余部分。为此,通常应该把 <script> 元素放到页面末尾,介于主内容之后及</body> 标签之前。

  • 可以使用 defer 属性把脚本推迟到文档渲染完毕后再执行。推迟的脚本总是按照它们被列出的次序执行。

  • 可以使用 async 属性表示脚本不需要等待其他脚本,同时也不阻塞文档渲染,即异步加载。异步脚本不能保证按照它们在页面中出现的次序执行。

  • 通过使用 <noscript> 元素,可以指定在浏览器不支持脚本时显示的内容。如果浏览器支持并启用脚本,则 <noscript> 元素中的任何内容都不会被渲染。