一、<script>、<script defer> 以及 <script async>
的区别,以及适用场景
浏览器在执行HTML的时候如果遇到<script>
时会停止页面的渲染,去下载和执行js的文件直接遇见</scirpt>
会继续渲染页面。故浏览器在执行js文件的时候浏览器表现为一片空白,为了解决这个问题ECMAScript
定义了defer
和async
两个属性用于控制JS的下载和执行
- defer
这个属性的用途是表面脚本在执行时不会影响页面的构造。也就是说,脚本会被延迟到整个页面都解析完毕后再运行。因此,在<script>
元素中设置 defer 属性,相当于告诉浏览器立即下载,但延迟执行。
HTML5规范要求脚本按照他们出现的先后顺序执行,因此第一个延迟脚本会先于第二个延迟脚本执行,而这两个脚本会先于DOMContentLoaded
事件执行。在现实当中,延迟脚本并不一定会按照顺序执行,也不一定会在DOMContentLoaded
时间触发前执行,因此最好只包含一个延迟脚本。
对于defer,我们可以认为是将外链的js放在了页面底部。js的加载不会阻塞页面的渲染和资源的加载。不过defer会按照原本的js的顺序执行.
- async
这个属性与defer
类似,都用于改变处理脚本的行为。同样与defer
类似,async
只适用于外部脚本文件,并告诉浏览器立即下载文件。但与defer
不同的是,标记为async
的脚本并不保证按照他们的先后顺序执行。
第二个脚本文件可能会在第一个脚本文件之前执行。因此确保两者之间互不依赖非常重要。指定async
属性的目的是不让页面等待两个脚本下载和执行,从而异步加载页面其他内容。
和defer
一样,会等待的资源不会阻塞其余资源的加载,也不会影响页面的加载。但是有一点需要注意下,在有async
的情况下,js一旦下载好了就会执行,也就是如果有多个js,谁先加载完就先执行谁,所以很有可能不是按照原本的顺序来执行的。如果js前后有依赖性,用async
,就很有可能出错。
总结:
这两个属性都会使script
标签异步加载,然而执行的时机是不一样的。
也就是说async
是乱序的,而defer
是顺序执行的,这也就决定了async
比较适用于百度分析
或者谷歌分析
这类不依赖其他脚本的库。从图中可以看到一个普通的<script>
标签的加载和解析都是同步的,会阻塞DOM的渲染,这也就是我们经常会把<script>
写在 <body>
底部的原因之一,为了防止加载资源而导致的长时间白屏,另一个原因是js可能会进行DOM操作,所以要在DOM全部渲染完后再执行。
async
比较适用于百度分析
或者谷歌分析
这类不依赖其他脚本的库,如下:
<!-- Global site tag (gtag.js) - AdWords: xxxxxx -->
<script async src="https://www.googletagmanager.com/gtag/js?id=AW-xxxxxx"></script>
<script>window.dataLayer = window.dataLayer || []; function gtag(){dataLayer.push(arguments);} gtag('js', new Date()); gtag('config', 'AW-xxxxxx');</script>
<!-- Global site tag (gtag.js) - AdWords: xxxxxx -->
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src='https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);})(window,document,'script','dataLayer','GTM-{( $pageGlobal.GTMID )}');</script>
<!-- End Google Tag Manager -->
复制代码
《WebKit技术内幕》:
1. 当用于输入网页URL的时候,WebKit调用其资源加载器加载该URL对应的网页。
2. 加载器依赖网络模板建立连接,发送请求并接受答复。
3. WebKit接收到各种网页或者资源的数据,其中某些资源可能是同步或异步获取的。
4. 网页被交给HTML解释器转变成一系列的词语(Token)。
5. 解释器根据词语构建节点(Node),形成DOM树。
6. 如果节点是JavaScript代码的话,调用JavaScript引擎解释并执行。
7. JavaScript代码可能会修改DOM树的结构。
8. 如果节点需要依赖其他资源,如图片、css、视频等。调用资源加载器来加载他们,但是他们是异步的,不会阻碍当前DOM树的继续创建;如果是JavaScript资源URL(没有标记异步方式),则需要停止当前DOM树的创建,直到JavaScript的资源加载并被JavaScript引擎执行后才继续DOM树的创建。
复制代码
所以,通俗来讲,chrome浏览器首先会请求HTML文档,然后对其中的各种资源调用相应的资源加载器进行异步网络请求,同时进行DOM渲染,直到遇到<script>
标签的时候,主进程才会停止渲染等待此资源加载完毕然后调用V8引擎对js解析,继而继续进行DOM解析。我的理解如果加了async
属性就相当于单独开了一个进程去独立加载和执行,而defer
是和将<script>
放到<body>
底部一样的效果。
最稳妥的办法还是把<script>
写在<body>
底部,没有兼容性问题,没有白屏问题,没有执行顺序问题。 参考
可以看一下目前的smarty项目,项目中的script标签应该是插入在了所有scprit标签的最下边。
二、 title
与 h1
的区别、 b
与 strong
的区别、 i
与 em
的区别
title
与h1
的区别
title
是网站 header
部分的内容,是网站的标题,而 h
表示 body
内的标题
b
与strong
的区别
从视觉效果上看是没有区别的 <b>
是一个格式,bold,格式本身为粗体文本,是一个字体加粗标签,没有语义强调的意思。 <strong>
是强调语气,强调部分重要的语句以及字体,默认效果是通过字体加粗来表示语义强调。 3. i
与 em
的区别
em单纯斜体,i没有实际意义搜索引擎更好抓取。都是在网页中以斜体显示的,但em的目的是出自强调。
<em>
是单词emphasis(强调)的缩写,<i>
是italic(斜体字)的缩写,推荐使用<em>
标签。
从视觉效果上看,b与strong、i与em是没有区别的,唯一的区别是搜索引擎检索的时候搜索引擎可以识别strong、em标签、而不能识别b与i标签
三、data- 属性的用法(如何设置,如何获取),有何优势
- 设置方法
a.直接在标签内书写,格式如下
<div id="test" data-age="24">
Click Here
</div>
复制代码
b.用js设置
方法一
var test = document.getElementById('test');
test.dataset.my = 'fruit'
方法二
test.setAttribute('data-name','bro')
推荐使用dataset
貌似setAttribute性能更好,但在处理少量data数据时,基本没有区别。切dataset更具有可读性。因此dataset操作是上选。
复制代码
效果
<div id="test" data-age="24" data-my="fruit" data-name="bro">
Click Here
</div>
复制代码
2.获取方法
var test = document.getElementById('test')
test.dataset.my = 'Byron'
test.setAttribute('data-name','fruit')
test.onclick = function () {
alert(this.dataset.my + ' '+ this.getAttribute('data-name') + ' ' + this.dateset.age )
}
复制代码