JavaScript高级程序设计(第4版)-第2章:HTML中的JavaScript
第2章 HTML中的JavaScript
2.1 <script>元素
<script>元素最初是Netscape公司在Navigator 2中实现的,具有下列8个属性:
- src(路径):外部文件路径
- async(异步):只对外部脚本文件有效,表示立即开始下载脚本,不阻止其它页面动作(下载资源、等待其它脚本加载等)
- defer(延时):只对外部脚本文件有效,表示将脚本延迟到文档完全被解析和显示之后再执行(在IE7及其更早版本中,defer对行内元素也起作用)
- integrity(完整性):允许比对接收到的资源和指定的加密签名以验证子资源完整性(SRI,Subresource Intagrity)。当接收到的签名和integrity属性指定的值不匹配时,网页报错。该属性一般用于对CDN(内容分发网络,Content Delivery Network)资源进行验证
- language(语言):废弃属性,最初用于表示代码中的脚本语言,已被type属性代替
- type(类型):表示代码块中的脚本语言内容类型(MIME类型),使用它需要注意以下几点:
- 惯例该值一般是"text/javascript",但是事实上这种用法已经被废弃了
- JavaScript文件的type一般是"application/x-javascript",但可能会导致脚本被忽略
- 除IE浏览器之外,这个值还可以是"application/javascript"和"application/ecmascript"
- type=module时,代码作为ES6模块,可以出现export和import关键字
- charset(字符):指定src属性所使用的代码字符集,一般很少使用
- crossorigin(跨源):配置相关请求的CORS(跨源资源共享),默认不使用,有如下两个值:
- crossorigin="anonymous" : 匿名,配置文件请求不必设置凭据标志
- crossorigin="use-credentials" : 设置凭据标志,出站请求包含凭据
使用JavaScript的两种方式:
- 行内嵌入
- 外部引入
使用<script>标签的几个注意点:
- <script>内部的代码是从上到下解释的
- <script>中代码被计算完成之前,页面的其余内容不会被加载或者显示
- 在<script>如果存在含有</script>字样的字符串,需要在前加转义字符
<script> console.log("<\/script>"); </script> - 和解释script定义的行内代码一样,在解释src引入的外部JavaScript文件时也会出现阻塞
- 在XHTML中可以忽略结束标签
- JavaScript惯例扩展名是js,但是并非必须,浏览器不会检查js文件的扩展名,但是服务器经常根据文件扩展来确定响应正确的MIME类型,这种扩展名自由的用处有以下几点:
- 方便服务器端脚本语言动态生成JavaScript代码
- 方便在浏览器中将JS扩展语言(TS、JSX等)转义为JavaScript代码
- 如果在设置了src属性的同时还添加了行内js代码,浏览器会忽略行内代码,优先引入外部js文件
- <script>支持外部域的JavaScript文件,这时的src可以指向和html页面不在同一个域中的url资源,integrity完整性属性就是针对跨域获取脚本文件的功能服务的。
2.1.1 标签位置
过去的习惯是将<script>标签全都写在<head>中,方便和css一起对外部文件进行管理,但是由于这种方式需要将外界Js页面都下载、解析、解释完后才开始渲染页面,延迟会降低用户的交互体验,因此现在的习惯是将script引入放在<body>的最后面。
2.1.2 推迟执行defer属性
defer属性只作用于外部脚本文件(除IE4-7),设置了defer属性的脚本会被延迟到整个页面都解析完毕后才会执行,相当于告诉浏览器:立即下载,但延迟执行。
单个添加了defer属性的脚本会在DOMContentLoaded事件之前执行,但如果是多个添加了defer的脚本,则实际情况可能会有偏差。
因此,比起使用defer,还是更推荐将要延迟执行的脚本放在页面底部的方法。
XHTML中的defer属性应该写为
<script defer="defer"></script>
2.1.3 异步执行async属性
async属性只适用于外部脚本,相当于告诉浏览器:立即下载,但不必等脚本下载完之后再加载页面或其他脚本。因此async异步脚本不应该在加载期间修改DOM。
async脚本一定会在页面的load事件前执行,但是对于DOMContentLoad却并不确定。
在XHTML中,async属性应该写为
<script async="async"></script>
2.1.4 动态加载脚本
也可以通过向DOM中动态添加script元素来加载指定脚本。
<script>
let script = document.creatElement("script");
script.src="index.js";
document.head.addChild(script);
</script>
注意:这种动态DOM添加的方法创建的script是异步脚本,默认带有async属性,但是这里就出现问题了,因为所有的浏览器都支持creatElement方法,但是不是所有浏览器都支持异步脚本,因此还需要对创建出来的脚本手动进行同步加载属性添加。
script.async = false;
这种方式获取的资源对浏览器预加载器是不可见的,会影响它们在资源获取队列中的优先级。因此会影响性能。
可以通过文档头部显式声明的方式让预加载器知道这些动态添加的脚本的存在。(注意不要漏掉as属性,否则有些浏览器会警告)
<link ref="preload" href="index.js" as="script">
2.1.5 XHTML中的变化
XHTML,Extensible HyperText Markup Language,可扩展超文本标记语言。是将HTML作为XML的应用重新包装的结果。
在XHTML中<script> 使用JavaScript必须将type设置为text/javascript
如果需要指定XHTML模式,可以将MIME的type指定为application/xhtml+xml(不是所有浏览器都适用)
在XHTML中代码编写规则非常严格,比如小于号<会被解释成一个标签的开始,必须使用实体形式(<)来代替。
也可以使用CDATA块,CDATA即文档中可以包含任意文本的区块。使用格式如下:
<script type="text/javascript"><![CDATA[
代码内容
]]></script>
不过对于一些不兼容XHTML的浏览器中就不支持CDATA块(XHTML,我真的栓Q),因此可以将CDATA标记和JavaScript注释一起使用来兼容所有浏览器。
<script type="text/javascript">
//<![CDATA[
代码内容
//]]>
</script>
2.1.6 废弃的语法
以前为了兼容不使用<script>标签的浏览器(Mosaic),会使用如下形式的代码:
<script>
<!--
代码内容
-->
</script>
看来不同的注释方式确实是浏览器兼容最喜欢的方法
2.2 行内代码与外部文件
相比起行内代码,使用外部文件的优势如下:
- 可维护性
- 缓存:根据浏览器对脚本文件的缓存机制,如果多个页面使用同一个脚本文件,则只需下载一次
- 适应未来:确保HTML版本更新不会影响到脚本文件的读入
配置浏览器请求外部文件最重要的一点就是:带宽占用。在使用了SPDY/HTTP2的浏览器中,独立JavaScript组件更具优势,但JavaScript分装的具体策略还是要根据浏览器的配置来考虑。
2.3 文档模式
文档模式doctype这个概念由IE5.5发明(不愧是你),有三种类型,区别只体现在CSS渲染内容方面,但是会对JavaScript产生一些副作用:
- 混杂模式(quirks mode)
- 功能:让IE做到一些非标准的特性
- 声明格式:标注/省略文档开头的doctype声明
- 标准模式(standards mode)
- 功能:让IE能够兼容标准
- 声明格式:
<!--HTML 4.01 Strict -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!-- XHTML 1.0 Strict-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<!--HTML5-->
<!DOCTYPE html>
- 准标准模式(almost standards mode)
- 功能:功能是支持了,标准规定了但没完全规定(这些个浏览器开发商我真的栓Q)
- 声明格式:分为过渡性文档类型(Transitional)和框架集文档类型(Frameset)触发
<!-- HTML4.01 Transitional -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<!-- HTML4.01 Framset -->
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Framset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<!-- XHTML 1.0 Transitional -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml/DTD/xhtml-transitional.dtd">
<!-- XHTML 1.0 Frameset -->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN" "http://www.w3.org/TR/xhtml/DTD/xhtml-frameset.dtd">
一般情况下并不区分标准模式和准标准模式
2.4 <noscript>元素
<noscript>用于给不支持JavaScript的浏览器提供替代内容,可以包含任何可以出现在<body>中的HTML元素,除了<script>。
下面两种情况下,<noscript>中的内容可以被渲染出来:
- 浏览器不支持脚本
- 浏览器对脚本的支持被关闭

浙公网安备 33010602011771号