概述
重学JavaScript系列——(二)HTML中的JavaScript
博主以扎实JavaScript基础为目的,以《JavaScript高级程序设计(第四版)》为核心参考资料,以一个“复习者”的角度有针对性地来创作这期专栏。文章加入了博主的很多思考和开发经验,关注初学JavaScript时容易忽略的地方,着重总结了ECMAScript新标准知识点的特性和应用场景。最终,本专栏将覆盖完整的JavaScript知识体系,以辅佐各路豪杰在开发路上的稳步前进。
专栏传送门:https://blog.csdn.net/huoyihengyuan/category_10586561.html
文章目录
- 重学JavaScript系列——(二)HTML中的JavaScript
- 2.1 script标签
- 2.1.1 标签位置
- 2.1.2 推迟执行脚本
- 2.1.3 异步执行脚本
- 2.1.4 动态加载脚本
- 2.1.5 XHTML中的变化
- 2.1.6 废弃的语法
- 2.2 行内代码和外部文件
- 2.3 文档模式
- 2.4 noscript标签
- 小结
将JavaScript引入网页,首先就要解决它和网页主导语言HTML的关系。在JavaScript早期,网景公司的工作人员希望在将JavaScript引入HTML的同时,不会导致页面在其他浏览器中出现渲染问题。当今,我们以这种机制为基础实现了更多的东西。当初他们的很多工作被保留到HTML规范中,致敬网景公司。
2.1 script标签
将JavaScript引入到HTML中的主要方法就是使用<script>元素。这个元素最初由网景公司创造,最早在Netscape中实现。
<script>元素主要属性:
属性 | 描述 |
---|---|
src | 可选。要执行的代码外部文件。 |
type | 可选。表示代码块中脚本语言的内容类型(也称MIME类型)。如果这个值被设为“module”,则代码会被当作ES6模块,有且只有这时,代码中才能出现import和export关键字。 |
async | 可选。表示应该立即下载文件,但不能阻止页面其他动作,比如下载资源或等待其他脚本加载。只对外部文件有效。 |
defer | 可选。表示文档解析和显示完成后再执行脚本。只对外部文件有效。 |
crossorigin | 可选。配置相关请求的CORS。普通的<script>标签只向window.onerror反馈少量信息(“Script Error”),如果设置了crossorigin属性,并在服务端设置了Access-Control-Allow-Origin响应头,就可以在window.onerror中反馈更详细的日志信息 |
integrity | 可选。比对制定的加密签名和下载的资源,以验证子资源完整性(SRI,Subresource Integrity)。如果不匹配,则页面报错,脚本不会执行,可以确保CDN不会提供恶意内容。 |
language | 可选。~~最初表示代码块中脚本语言。~~大多数浏览器都会忽略这个属性,不应该再使用它。 |
charset | 可选。~~使用src属性指定的代码字符集。~~很少用,大多数浏览器不在乎它的值。 |
使用<script>的方式主要有两种:通过它直接在网页中JavaScript代码,和通过它在网页中包含外部JavaScript代码。
其实,<script>中的代码会被从上到下解释,在代码被计算完成之前,页面的其余内容不会被加载,也不会被显示。
在使用行内JavaScript代码时,代码中不能出现</script>,想要避免这个问题,只需要个转义字符“”即可.
console.log('</script>');
按照惯例,外部JavaScript的文件扩展名是“.js”,但这不是必须的,因为浏览器不会检查JavaScript文件扩展名。这就方便了服务器端脚本语言动态生成JavaScript代码,以及在浏览器中将JavaScript扩展语言(如TypeScript、React的JSX)转译为JavaScript。
另外,使用了src属性的<script>元素不应该再在标签内包含其他JavaScript代码。如果二者都存在的话,则浏览器会忽略行内代码。
我们或许利用过<script>的src不受浏览器同源策略的影响的特性,去做一些跨域的操作。最常见的场景就是直接拷贝某些包含CDN链接的开源库<script src=“http://www.cdn.xxx.com/xxx.min.JavaScript”>,从而方便将之引入到我们的html文件中。然而,引用了放在别人服务器上的JavaScript文件要格外小心,因为恶意的程序员可能会把对应的文件替换成恶意代码。<script>的integrity属性可以防范这个问题,但这个属性不是所有浏览器都支持。为了保证网站的安全性,还是推荐将代码放到自己的服务器上。
当然,在没有使用defer和ansyc属性的情况下,浏览器总会按照<script>在页面中出现的顺序依次解释它们。
2.1.1 标签位置
在页面加载过程中,当在浏览器解析到<body>时才开始渲染,在此之前浏览器窗口显示空白。
过去,所有<script>元素被放到<head>中,对于需要很多JavaScript的页面,用户会感觉到明显的渲染延迟,即出现白屏期。为了解决这个问题,现代Web应用程序通常将所有的JavaScript引用放到body内容主体之后、</body>标签之前。这样一来,页面在处理JavaScript代码之前完全渲染页面,用户会感觉页面加载更快了,因为浏览器显示的空白时间缩短了。
2.1.2 推迟执行脚本
在<script>元素上设置defer属性,会告诉浏览器立即下载对应文件,但会将脚本的执行延迟到</html>解析完成后,即整个页面解析完成之后。但会在DOMContentLoaded事件之前执行。
HTML5明确规定,defer只对外部脚本文件有效,但在不支持HTML5的浏览器上,则会表现出旧的行为。所以,为了让代码尽可能地兼容更多的浏览器,我们还是把这些需要延迟执行的代码放到页面底部比较好。
对于XHTML文档,指定defer的属性应该写成defer=“defer”的形式。
2.1.3 异步执行脚本
<script>中还有个async属性,和defer类似,都会告诉浏览器立即下载,并且也只适用于外部脚本。不过与defer不同的是,async标记的脚本并不能保证它们出现的次序。
对于XHTML文档,指定async的属性应该写成async=“async”的形式。
关于defer和async的执行区间可以参考这张图:
2.1.4 动态加载脚本
除了在设计页面时直接引入<script>标签,还可以动态加载脚本。
一种常见的解决跨域问题的方案jsonp,就是利用<script>等标签不受同源策略影响的机制进行解决跨域问题。通过DOM API动态添加<script>元素的方式就是动态加载脚本,只要创建一个<script>元素并将其添加到DOM即可。
let script = document.createElement('script')
script.src = 'A.js'
document.body.appendChild(script)
默认情况下,通过这种方式创建的<script>元素是以异步方式加载的,相当于添加了async属性,但不是所有浏览器都支持async属性,因此要统一动态脚本的加载行为,可以明确其设置为同步加载:
let script = document.createElement('script')
script.src = 'A.js'
script.async = false
document.body.appendChild(script)
但仅仅是这样的动态加载脚本有个性能问题。这种方式获取的资源对浏览器预加载器是不可见的,这会影响它们在资源获取队列的优先级。想要预加载器知道这些动态请求文件的存在,可以在文件头部显式声明它们:
<link rel="preload" href="A.js">
2.1.5 XHTML中的变化
XHTML是将HTML作为XML重新包装的结果,可以理解为“严格的HTML”。虽然它已退出历史舞台,但在实践中偶尔会遇到遗留代码,所以这里简单提一下。
XHTML在语法上我们要注意更多的细节。比如,在<script>里小于号<
会被解释成一个标签的开始,但实际上我们只是想做条件判断。虽然这种情况也可以用“符号实体(如<)”或“CDATA块”方案来解决,但如果不支持CDATA的浏览器又要考虑如何优雅的降级。
程序的编写应该越来越简单,而不是越来越复杂。但在当时的情况下,XHTML的过渡作用,证明了一代人在完善这套体系时,做出了不断的努力和创新,致敬!
2.1.6 废弃的语法
来回顾一下历史。
历史上存在这样一种情况:过去某些浏览器不支持JavaScript,所以如果含有<script>的代码会被打印到页面上,破坏页面外观。
对于这种代码,当时有一个解决方案:
<script><!--
function sayHi(){
console.log("Hi");
}
//--><script>
这样,不支持JavaScript的浏览器就会忽略<script>标签里面的内容,支持JavaScript的浏览器就会运行脚本代码。
2.2 行内代码和外部文件
我们虽然可以直接在HTML中嵌入JavaScript代码,但大多数情况下最佳实践还是通过外部文件进行引入。理由如下:
- 可维护性——开发者可以统一管理JavaScript代码,结构也可以更加清晰。
- 缓存——浏览器的特定缓存设置,对于多个页面同一个文件,只需要下载一次。
- 适应未来——外部文件引入的方式,使我们不必考虑XHTML的某些问题,而且越来越多的工具或IDE也可以让我们对单独的JavaScript文件做出更多定制化工作。比如“ESlint代码规范校正”。
2.3 文档模式
文档模式是给浏览器看的,告诉浏览器要以什么标准来解析文档。
最初的文档模式有两种混杂模式和标准模式,后来又出现了准标准模式。
不过,现在只需要记得,在当前主流的实际开发中,我们始终使用HTML5的规范:
<!DOCTYPE html>
声明对大小写不敏感。不过一定要放到
<html>之前,作为文本第一行。
2.4 noscript标签
<noscript>会出现在某些平台HTML文件的初始化代码中,在当浏览器不支持脚本或者是脚本被禁用时,显示<noscript>里面的内容。
虽然当前浏览器几乎已经100%支持JavaScript了,脚本被禁用的情况也少之又少,但是它还是有存在的必要的。毕竟,我们是一群严谨的程序员,当然也可以留下个友好的彩蛋。
小结
在HTML中加入JavaScript脚本代码,相当于为HTML静态页面赋予了“神经”。为了更有安全感地驾驭这套“神经冲动”,我们通过<script>的defer或async控制它的下载队列,并聊了聊一些安全性和兼容性问题。
如何在网页中引入代码,取决于我们这些开发者的习惯。但为了匹配更完美的结果,我们会使用一些细节方面的最佳实践方案。
这一期是HTML中的JavaScript,也介绍了一部分历史上引入JavaScript的变迁过程。作为最前线的一批开发者,我们可以用最新的标准和规范,来为推动前端发展贡献一点自己的力量。
最后
以上就是野性长颈鹿为你收集整理的重学JavaScript系列——(二)HTML中的JavaScript重学JavaScript系列——(二)HTML中的JavaScript的全部内容,希望文章能够帮你解决重学JavaScript系列——(二)HTML中的JavaScript重学JavaScript系列——(二)HTML中的JavaScript所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复