简介

  • HTML定义网页内容
  • CSS描述网页布局
  • Javascript控制网页行为

Javascript主要包含:核心部分(ECMAscript)、文档对象模型(DOM)、浏览器对象模型(BOM)。

ECMAscript

ECMAscript定义了Javascript的基本规范,并不涉及浏览器部分。

目前的Javascript均是ECMAscript结合浏览器的拓展。

DOM

文档对象模型(Document Object Model)是一个应用编程接口(API)。

提供与网页内容交互的方法与接口。

DOM Tree

用于在HTML中使用拓展的XML。

DOM通过创建表示文档的树,从而控制网页内容和结构。

BOM

浏览器对象模型(Browser Object Model)可以访问和操作浏览器窗口。

提供了与浏览器交互的方法和接口。

HTML中的Javascript

<script>标签加载脚本

将Javascript脚本插入HTML的主要方法是使用<script>元素。

属性:

  • async:可选,表示立即开始下载脚本,但不能阻止其它页面动作。
  • charset:可选,很少使用,一般浏览器不在乎这个值。
  • crossorigin:可选,配置相关请求的CORS(跨资源共享)。默认不使用CORS。
  • defer:可选,表示脚本延迟到文档完全被解析和显示后执行。只对外部脚本有效。
  • integrity:可选,允许比对接收到的资源和指定的加密签名以验证资源完整性(SRI)。
  • language:废弃,使用type属性替代。
  • sec:可选,包含要执行的代码的外部文件。
  • type:可选,表示代码块中脚本语言的类型(MIME类型),按照惯例,这个值始终是“text/javascript”。

使用它有两种方式:

  1. 直接在网页中嵌入JavaScript代码。
  2. 包含外部Javascript文件。

行内脚本与外部脚本

行内脚本

1
2
3
4
5
<script>
funtion sayScript(){
console.log("<\/script>");
}
</script>

包含在标签内的代码会被从上到下解释。如上所示,被解释的是函数定义,该函数会被保存在解释器环境中。

在<script>元素中代码被解释完之前,页面其余内容不会被加载和显示。

注意:代码中若出现</script>,需要在前面加入【\】转义字符进行转义,否则会被浏览器当作标签结束。

外部脚本

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

与行内脚本一样,解释外部JS文件时,页面也会被阻塞。

注意:使用src属性的<script>元素不应该再包含行内脚本,即便包含,也会被忽略。

标签位置

过去常把<script>元素放到head标签中,这样做的好处是将CSS和JavaScript集中到一起。

但是,这样会导致,全部JavaScript脚本被下载、解析完成后,才能开始渲染网页。(网页在浏览器解析<body>时开始渲染)

对于需要很多JavaScript脚本的页面,这样会导致加载期间浏览器完全空白,降低网页浏览速度。

现代Web应用程序通常将所有JavaScript放在<body>标签的末尾。

1
2
3
4
5
6
7
8
9
10
11
!<DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
</head>

<body>
<!-- 这里是页面内容 -->
<script defer src="example.js"></script>
</body>
</html>

脚本执行方式

推迟执行脚本

defer属性用于推迟执行脚本,即在整个页面被解析后(解析到</html>标签)才会运行。

1
2
3
4
5
6
7
8
9
10
11
12
!<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>

两个js脚本会按照原来的顺序执行,只是被推迟执行。

注意:defer属性只对外部脚本有效。

异步执行脚本

async属性用于异步执行脚本。

1
2
3
4
5
6
7
8
9
10
11
12
!<DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script async src="example1.js"></script>
<script async src="example2.js"></script>
</head>

<body>
<!-- 这里是页面内容 -->
</body>
</html>

与defer的不同在于,两个并列的脚本不会严格按顺序执行,即不一定先执行哪个脚本。

注意:async属性只对外部脚本有效。

动态加载脚本

除了使用<script>标签加载脚本,还可以用其它方式加载。

因为JavaScript可以使用DOM API,所以通过DOM动态添加script元素也可以加载指定脚本。

只需要创建一个script元素,并加入到DOM中即可:

1
2
3
let script = document.creatElement('script');
script.src = 'gibberish.js';
document.head.appendChile(script);

以这种方式创建的script标签是异步加载的,相当于添加了async属性。

这种动态加载对浏览器预加载器是不可见的,严重影响它们在资源获取队列中的优先级和性能。

解决方案是让预加载器知道这些动态请求的存在,可以在文档头中显式声明:

1
<link rel="preload" hred="gibberish.js">

<noscript>

<noscript>标签早期是针对不支持JavaScript脚本的浏览器发明的,被用于给这些浏览器提供替代内容。

虽然如今浏览器普遍支持JavaScript,但对于某些禁用JavaScript脚本的浏览器,这个元素依旧有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
!<DOCTYPE html>
<html>
<head>
<title>Example HTML Page</title>
<script async src="example1.js"></script>
<script async src="example2.js"></script>
</head>

<body>
<noscript>
<p>This page requires a JavaScript-enable browser. </p>
</noscript>
</body>
</html>

若浏览器不支持或禁用JavaScript脚本,则会显示noscript标签中的内容。