「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
本章学习内容:
- 使用
- 行内脚本与外部脚本的比较
- 文档模式对JavaScript有什么影响
- 确保JavaScript不可用时的用户体验
-
元素
包含在
外部引用代码只需要使用src这个属性,向其传入一个URL,指向包含JavaScript的文件:
<script src="main.js"></script>与行内文件一样,解释外部JavaScript文件时,页面也会阻塞。
此外,如果一个script既有src又有行内文件,此时的script只会解释引入文件,不会解释行内文件。
浏览器在解析资源的时候,会向src属性指定的路径发送一个get请求,以获得相应的资源,并假定这个资源就是JavaScript文件,所以这个请求不会受到浏览器同源策略的限制,但是如果确认时JavaScript文件时,其返回和执行就会受到限制。并且也会受到来自父页面HTTP/HTTPS协议的限制。
一个外部引用的文件会当做所加载页面的一部分加载解释,这使得我们可以从不同的域分发JavaScript。此时如果引用外域的文件则需要考虑改文件会不会被篡改。以保证页面正常显示。
只要是通过script引用的文件,都会按照其在页面出现的顺序依次解释。前提是他们都没有defer和async属性。此时后面的代码必须等待前面的解释完才能开始解释。
-
标签位置
过去script都被放在了head内部:
<!DOCTYPE html> <html> <head> <title>script</title> <script src="1.js"></script> <script src="2.js"></script> </head> </html>这样做是为了将CSS和JavaScript集中起来,不过这样就会导致在JavaScript没有全部下载完成之前,是不会被有页面显示的。这通常会导致实现的显示延迟。所以此后的script通常会被放到元素之后。
<!DOCTYPE html> <html> <head> <title>script</title> </head> <body> <script src="1.js"></script> <script src="2.js"></script> </body> </html> -
推迟执行脚本
script中有一个defer属性,这个属性这个脚本会在整个页面执行完毕之后再执行。在
<!DOCTYPE html> <html> <head> <title>script</title> <script defer src="1.js"></script> <script defer src="2.js"></script> </head> </html>虽然1.js和2.js写在了head中,但是他们会等到浏览器解析到之后才会执行,并且按照出现的顺序执行。两者都会在DOMContentLoaded事件之前执行。但是实际上defer脚本不一定会按照我们想要的顺序执行,所以一个页面最好只有一个defer脚本。
defer属性从IE4、Firefox 3.5、Safari 5 和 Chrome 7 开始的,所以其他浏览器会忽略,因此最好还是写在最后。
-
异步执行脚本
从改变脚本处理方式上看,async和defer类似。都只使用与外部,通知浏览器立即下载,稍后执行。但是async不能保证其执行顺序。async属性主要是告诉浏览器,不必等脚本下载和执行完再加载画面,也不必等该脚本执行完再执行其他脚本,因此,异步脚本不应出现在加载期修改DOM异步脚本会保证在load事件之前,但不保证在DOMContentLoaded的前后执行。
-
动态加载脚本
除了script,JavaScript还可以使用DOM API 加载脚本。只需要创建一个script元素加入到DOM即可:
let script = document.createElement('script'); script.src="main.js"; document.head.appendChild(script);当然,在添加HTMLElement之前是不会发送请求的,默认情况下,这种方式创建的script都是异步加载。相当于添加了async。不过虽然所有浏览器都支持createElement()方法,堵车不都支持async方法。所以可以明确使用同步方法
let script = document.createElement('script'); script.src="main.js"; script.async="false"; document.head.appendChild(script);但是这种方式对于浏览器预加载是不可见的,会严重影响资源队列的优先级,可能会严重影响性能。如果需要让预加载器知道他们,需要头部声明:
<link rel="preload" href="main.js"></link> -
XHTML中的变化
可扩展超文本标记语言(XHTML)是将HTML作为XML应用重新包装的结果。在XHTML中,JavaScript必须指定type属性为"text/javascript",但是XHTML已经退出了历史舞台。
-
-
行内代码和外部文件
虽然script可以允许在页面内写入JavaScript,也可以通过外部引用,但是在日常实践的时候,我们会尽可能的将JavaScript代码写在外部文件中,不知道大家有没有想过这是外什么。
- 可维护性:JavaScript代码如果分散到多个HTML页面,会导致维护困难。而且用一个目录保存所有的JavaScript代码会更利于维护。
- 缓存:浏览器会根据特定的设置缓存所有外部链接的JavaScript文件,这意味着如果两个页面都用到同一个文件的话,并不需要下载两次。
- 适应未来:通过把JavaScript放到外部,就不需要考虑前文中的XHTML。因为外部文件对于HTML和XHTML都是一样的。
所以更加轻量的,独立的JavaScript组件向客户端送达脚本是更具有优势的。
-
文档模式
即可以使用DOCTYPE切换文档模式。最初文档模式只有混杂模式和标准模式。前者让IE能学习IE5(支持非标准特性),后者让IE具有兼容标准的行为。这两种模式最主要的区别在于CSS渲染上,但是对于JavaScript也有一些关联影响,被称为副作用,记住这个副作用,后面会多次提到。
随着浏览器的发展,文档模式又出现了:准标准模式。这种模式下浏览器支持多标准的特性,但是有没有规定的那么严格。主要区别在于对待图片元素周围的空白(表格中最为明显)
混杂模式可以不使用DOCTYPE声明作为开关,但是这并不合理,因为这样在各个浏览器中差异巨大,导致没有了浏览器一致性。
标准模式和准标准模式的差别就非常小了,文档模式的检测也不会区分,所以我们常说的标准模式就是除混杂模式之外的模式。
-
元素
虽然现在的浏览器100%都支持了JavaScript,但是还会有禁用JavaScript的浏览器,这时就需要,该元素可以包含任何可以出现在中的HTML元素,script除外。
只有在下列两种情况下,浏览器才会显示其中内容:
- 浏览器不支持脚本
- 浏览器对脚本的支持被关闭
满足其一,中的内容就会被渲染,反之就不会。
总结:
- script有两种解释方式,8中属性。
- 外部文件必须在src中写入url,并且需要注意同源问题。
- script可以放到head中也可以放到body中,但是推荐放到body底部,因为script执行会阻塞页面。并且如果没有defer或者async属性的话,会按照出现顺序解释。
- JavaScript推荐写成外部文件。利于维护,缓存,兼容XHTML。
- 文档模式用于支持一些非标准模式,除混杂模式都称为标准模式。
- 在不支持脚本的浏览器使用,可以解释脚本