在HTML中使用JavaScript

关于 script 标签


向 HTML 页面中插入JavaScript的主要方法,就是使用 <script> 标签,这个元素有6个属性:

  1. async,异步下载,用于控制下载,即在下载这个文件的同时,后面的工作也可以进行,只对外部脚本有用。
  2. charset,一般情况下用不上,因为大多数浏览器会忽略它的值,但在出现乱码时,这个属性可能会帮上忙,如在 JS 中遇到了中文或其他国家的语言,这时有可能会使用到这个属性,但使用的频率不高,基本上是不用管的。
  3. defer,延迟执行,表示脚本可以延迟到文档完全被解析和显示之后再执行,只对外部脚本有用,但也有例外,IE7及更早的的版本对嵌入脚本也支持这个属性。
  4. language,已废弃,表示编写代码使用的脚本语言。现在基本上是用不到了,所以不用管啦。
  5. src,最重要的属性,表示当前需要下载或执行的 JS 文件所对应的位置,是开发中最常用的属性,只记住这个就行了。
  6. type,可以当成是 language 的代替属性,但在平常开发中也很少使用。如果你在页面中正常插入了 <script> 标签的话,默认情况下就是使用了 text/javascript 这种形式,这是浏览器默认指定的,所以不使用这个属性也完全不影响正常使用。用于表示编写代码使用的脚本语言的类型,也就是 MIME 类型(多用途互联网邮件拓展) ,是控制服务器与浏览器之间传输的一种形式,在设置动态 JS 的时候会用得上。另外,我们平时如果在 <script> 标签中设置了 type 属性,一般会把它的值设置为 text/javascript,但实际上服务器在传送 JS 文件的时候使用的 MIME 类型通常是 application/x-javascript,,但是不要自己把 type 属性设置成这个值,因为这可能会导致脚本被忽略。

JS 运行原理


JS 的运行原理:先预处理,再执行。这两个加在一起就叫解释,而且这是是一个阻断式的操作,也就是说在解释器运行 JS 时,所有其他的事情全都停止。

JS 在进行预处理的时候,会有一个变量提升的操作。

/*** 情况一 ***/
var foo;
console.log(foo); // undefined

/*** 情况二 ***/
var foo;
console.log(foo); // undefined
foo = 123;

/*** 情况三 ***/
console.log(foo); // undefined
var foo = 123;

因为存在变量提升,所以情况三跟情况二其实是一样的。提升会把声明提前,但是不会把赋值操作提前,情况三中 console.log(foo) 在赋值操作之前,所以 foo 还是 undefined。但是 JS 对函数的预处理又稍有不同,它会把整个函数先找个地方储存起来,所以即使函数调用写在前面,函数声明写在后面,函数体内的语句依然能执行。

foo(); // 正常执行

function foo() {
    console.log(123);
}

/*** 相当于以下代码 ***/

function foo() {
    console.log(123);
}

foo();

使用 script 标签的问题


  1. 在代码中不要出现 ”</script>” 字符串,因为 JS 解释器在遇到这个字符串的时候会不知道这是要执行的代码,还是说要把 JS 结束掉,所以不要使用它。如果在特殊情况下非要使用,那要对字符串进行转义 ”<\/script>”。需要动态在页面上生成一段 JS 代码的情况下可能会需要用到这个字符串。
  2. 写 <script> 标签一定要使用 </script> 正常闭合,不要使用 <script /> 这种不符合 HTML规范的语法,因为某些浏览器(尤其是 IE)会不支持。

关于 script 标签的 src 属性


src,最常见的用途就是引进外部的 JS 文件,但要知道一点,这个属性所对应的文件不一定是 JS 文件,也可以是其他类型的文件,只不过我们最常用的就是 JS 而已。可能在某些特殊的情况下,我们需要动态地生成一些 JS,用到了其他语言如 php,这时候链接的文件可能就不是一个拓展名为 .js 的文件了。一旦指定的不是 JS 文件,那么需要对返回文件的 type 类型做一下定义,确保服务器返回正确的 MIME 类型。

问题:如果一个 <script> 标签既引用了外部的 JS 文件,又在内部写了 JS 代码,会发生什么情况?

一般情况下,浏览器只会下载并执行外部的 JS 文件,内嵌的代码会被忽略。

引用的外部文件也可能不是在你的服务器上,这时候引出了 JS 的一大特性,跨域。我们可以去引用其他网站的图片,也可以引用其他网站的 JS,这个就叫跨域。

好处:可以去引一些插件库,或者把自己的文件统一放到一起便于维护,可以访问外部资源。

坏处:如果引用的 JS 文件不是你自己写的,你无法操作这个 JS 文件,一旦这个文件无法访问了,可能会出现一些问题。不过这个问题还好,更大的问题是,如果有人使坏,在这个 JS 文件里插入了一段恶意的脚本,如脚本攻击,或盗取用户的cookice,这种情况比较麻烦。所以在引用其他网站的 JS 时一定要小心,最好选一些知名度比较高的网站。

script 标签的位置


正常开发中,通常把 <script> 放在 </body> 前。因为 JS 是阻断式的语言,所以如果把 <script> 放在 <head> 里,可能出现的情况是,打开一个页面,浏览器去请求下载这个 JS 文件,然后运行,这个过程是需要一定时间的,而在这段时间里,页面是一片空白,因为 <script> 下面所有的东西都被阻断掉了,这样用户体验很不好。所以一般情况下把 <script> 放在页面最底端。

但如果某个 JS 一定要在页面的渲染之前执行,那就把 <script> 放到 <head> 里。一般这种情况是与 CSS 相关的,比如说在做手机开发的时候,需要要使用 rem 做单位,用根节点的相对大小来设置页面的距离单位,当页面渲染时,需要参考根节点的大小来进行设置。

延迟执行的问题


<head>
    <script defer=”defer” src=”example1.js”></script>
    <script defer=”defer” src=”example2.js”></script>
</head>

在没有设置 defer 属性的情况下,这两个脚本是按顺序执行的,但是设置了 defer 属性后,执行顺序就不一定了。虽然 HTML5 规范要求脚本按照它们出现的顺序执行,但是各浏览器实现机制不同,所以平常开发中不要使用延迟执行。如果两个脚本有关联关系,比如说第二个脚本中使用的变量是在第一个脚本中定义的,由于两个脚本的执行顺序是不确定的,情况很难把握。还有,使用延迟脚本可能会导致 DOMContentLoaded 事件在某些浏览器中不好用。所以开发中延迟脚本能不用就不用,只需要了解,在看到别人的代码时候遇到的话,知道是怎么回事就行。

内部脚本的问题


XHTML语法更严格,大括号和小括号是不被允许的,所以要在 XHTML 中插入 JS 代码的话,必要时需要使用转义符,但这可能会导致代码可读性很差。另一种方法是使用代码片段(CData片段),这是文档中一个特殊区域,可以在里面使用任意字符:

<script type=”text/javascript”><![CDATA[
    alert(“Hello World!”);
]]></script>

但是有些浏览器不兼容 XHTML,所以还需要把 CData 标记注释掉:

<script type=”text/javascript”>
//<![CDATA[
    alert(“Hello World!”);
//]]>
</script>

代码片段在平常开发中并不重要,但在国外的模板网站上可能会经常看到,稍作了解。

需要注意的是,如果 type 返回的 MIME 类型是 application/xhtml+xml,会默认触发 XHTML 模式,所以在使用浏览器返回 MIME 类型的时候要小心。

外部脚本 or 内部脚本 ?


外部脚本的优点:如果好几个网站使用同一个 JS 文件,这时候浏览器会自动地把这个文件缓存下来,这样会减少网络请求,让网速变快,提升访问速度。但在开发过程中可能会遇到一个问题,比如你修改了文件但在浏览器上却看不到对应的效果,这是因为浏览器之前把你的文件缓存起来了,而没有去下载修改过的文件。开发中避免缓存的常用方法有:

  1. 直接设置浏览器,在 Chrome或 Firefox 的控制台中开启禁用缓存的模式,或者每次开发时清理缓存。
  2. 在引用的 JS 文件名后加一个随机数,这样浏览器会认为这是不同的文件,所以不会缓存。

内部文件最大的好处就是性能上的提升,减少连接数,如果使用的是外部文件,需要通过网络请求下载文件,如果使用内部文件,可以减少网络请求。这种性能提升尤其体现在手机上,因为手机发送请求对性能的开销非常大,在电脑上可能影响不太大。

文档模式


文档模式就是告诉页面用哪种形式去解析你的文档,有混杂模式(quirks mode)和标准模式(standards mode),这两种模式主要影响 CSS 内容的呈现,对 JS 的影响不大。

现在我们用到的大部分编辑器都是内置了标准的文档模式,有两个快捷操作可以了解一下,新建一个页面,设置文件格式为 HTML 或 XHTML,在页面上输入 HTML:4S,再按 Tab 键,这时候大部分编辑器都会自动打出 HTML4 的标准文档模型。如果不考虑浏览器的兼容性并想用到一些更好的 CSS3 效果的话,可以在新建页面上输入 HTML:5,再按 Tab 键,这时候会生成一个 HTML5 的文档模型。

小结


要在 HTML 中要使用 JS 的话,最常用的方法就是使用 <script> 标签,这个标签有6个可选属性,第一个是async异步下载,第二个 charset 可设置语言类型,第三个defer延迟执行,第四个language,第五个 src 引用外部文件地址,第六个 type 类型,这6个属性中一般只需要用到 src,其他的都可以不写。另外,由 type 属性延伸了解了一下 MIME 类型。提到了使用 <script> 标签可能会遇到哪些问题,针对这些问题引出了 JS 的运行原理。JS 是预处理加执行的一门语言,而且在运行过程中是阻断式的,会把所有其他事情都停掉。如果在 JS 中使用到 </script>,一定到用转义符进行转义。要正确闭合 <script> 标签。src 属性最常引用的是 JS 文件,但也可以引用其他类型的文件,但引用其他类型文件时,要确保服务器返回正确的 MIME 类型。如果<script> 标签引用外部文件的同时也存在内部文件,则只执行外部文件。JS 是可以跨域的,也就是可以去引用不和你的服务器在同一个域名下的 JS 文件。关于<script> 标签的位置,放在页面顶部是传统的做法,但是这样会阻碍页面的渲染,所以正常开发中通常把它放在页面底部。如果是一定要在页面渲染前执行的文件,那就把它放在顶部。异步下载,延迟执行能不用就不要用。外部文件可以缓存,内部文件可以减少连接数,提升性能,需要使用哪个要结合情况自己衡量。

推荐大家去喜马拉雅收听沙翼老师的#陪你读书#教程,是一个非常好的前端音频教程。此文是对教程第二期的内容整理。

原文地址:https://www.cnblogs.com/sukiY/p/9240279.html