script 标签


要在浏览器中执行 JavaScript,可在一个 HTML 文件中编写<script></script>,并于两个标签间编写 JavaScript 代码。例如:

<script>
    let name = prompt('Input your name');
    alert(`Hello! ${name}!`);
</script>

按此看执行结果

上例中,promptalert是浏览器上全局对象上提供的函数,在浏览器中,全局对象就是window对象,代表浏览器本身,为Window的实例。当然,上面的 JavaScript 程序没什么作用,只是让你输入名称并显示而已。你可以将<script></script>放在 HTML 标签之中。例如:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
</head>
<body>
      JavaScript Example!<br>
      <script>
          let name = prompt('Input your name');
          document.write(`Hello! ${name}!`);
      </script><br>
      JavaScript Example!
</body>
</html>

按此看执行结果

默认情况下,浏览器在遇到<script></script>时,会停止文件解析,先执行<script></script>间的JavaScript,documentwindow全局对象上的特性,代表整份 HTML 文件,为Document的实例。如果执行documentwrite()方法,则会在<body>中目前文件解析点输出指定的文本,执行完<script></script>间的 JavaScript 后,再继续文件的解析。

基本上,浏览器会假设你使用的是 JavaScrip t语言,不过也可以用HTTP Content-Script-Type标头来指定,标头可以使用<meta>来摸拟,所以可以如下指定:

<meta http-equiv="Content-Script-Type" content="text/javascript">

也可以在<script>上使用type属性来指定。例如:

<script type="text/javascript">
    // 你的代码
</script>

type指定可以是 MIME(Multipurpose Internet Mail Extension)类型,一些可指定的范例有:

  • text/javascript
  • text/ecmascript
  • application/javascript
  • text/jscript
  • text/vbscript

第一个是 JavaScript 的官方名称,其它类型的指定,主要是看浏览器是否支持,例如在安装 IronPython 的情况下,甚至可以让 Internet Explorer 支持text/python的指定。

HTML4 规范了type属性,但在 HTML5 中为选用。在早期,<script>上还允许设定language属性,在 HTML 4 时标准化<script>标签时,并没有采纳language属性,有时会有一些早期编写的网页上看到这样的设定:

<script language="javascript">
    // 你的代码
</script>

language甚至也允许编写版本号,例如:

<script language="javascript1.2">
    // 你的代码
</script>

由于 HTML 4 并没有采纳language,现在已不建议设定,新版浏览器也会忽略这个属性,仅有时为了与旧版浏览器兼容,你会看到这样的设定:

<script type="text/javascript" language="javascript">
    // 你的代码
</script>

可以将<script></script>放在整份 HTML 文件之后,</body>之前,依照现在的最佳实践来说,应该这么做,因为 HTML 文件此时已经加载、解析完成,应有的 DOM 元素也已经产生,若 JavaScript 必须操作 DOM 元素,此时可以放心地进行操作。

也可以将<script></script>放在<head></head>之间,过去浏览器上的 JavaScript 代码,经常是这么做的。例如:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="text/javascript">
        let name = prompt('Input your name');
        document.write(`Hello! ${name}`);
    </script>
</head>
<body>
    JavaScript Example!
</body>
</html>

按此看执行结果

要注意的是,浏览器处理<head></head>间的JavaScript时,还没有解析<body>中的标签,所以上例中,documentwrite会直接从<body>的第一行开始。一般初学者常犯的错误是:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="text/javascript">
        let welcome = document.getElementById('welcome');
        welcome.innerHTML = `Hello! ${prompt('Input your name')}!`;
    </script>
</head>
<body>
    <span id="welcome"></span>
</body>
</html>

按此看执行结果

documentgetElementById可以根据 HTML 标签的id属性值获取 HTML 标签的 DOM 对象,innerHTML可设定实例的 HTML 内容(innerHTML在 HTML5 中是标准特性)。在执行上例的 JavaScript 时,<body></body>中的文件根本还没开始解析,所以<span id="welcome"></span>根本还不存在,所以获取的是undefined,根本无从设定innerHTML,若是将上例中的<script>代码移至</body>
之前,就不会有这个问题。

要等到全部文件资源完整加载后再执行指定的代码,也可以借助window.onload事件。例如:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="text/javascript">
        window.onload = function() {
            let welcome = document.getElementById('welcome');
            welcome.innerHTML = `Hello! ${prompt('Input your name')}!`;
        };
    </script>
</head>
<body>
    <span id="welcome"></span>
</body>
</html>

按此看执行结果

window对象的onload特性可以指定函数,当浏览器完成整份文件资源的加载后,如果onload特性有设定函数,就会予以调用,然而,完成整份文件资源的加载是指 HTML、CSS、图片等都被加载完成,而不是单指是 DOM 树创建完成,因此,如果文件资源非常的多,或者是网络速度不佳,那么在可以执行 JavaScript 的效果之前,访客看到的可能会是不完整的使用者接口。

可以将 JavaScript 程序编写在 .js 文件中,并使用<script>src属性指定文件名称。例如,将底下的程序写在一个 hello.js:

window.onload = function() {
    let welcome = document.getElementById('welcome');
    welcome.innerHTML = `Hello! ${prompt('Input your name')}!`;
};

如果上面的 .js 文件放在 js 文件夹中,则可以如下使用:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <script type="text/javascript" src="js/hello.js"></script>
</head>
<body>
    <span id="welcome"></span>
</body>
</html>

按此看执行结果(在 JS Bin 中,只要写在 JavaScript 页框中的代码,会自动嵌入 HTML 之中)。

虽然程序都在 .js 中,但<script></script>还是要成对出现,而<script></script>中出现的代码会被忽略。

在这边要注意编码的问题,浏览器会假设加载的 .js 文件编码与 HTML 网页编码相同。如果 .js 文件编码与 HTML 编码不同,JavaScript 中非 ASCII 兼容字符部份就会出现乱码。

例如,如果 .js 是 Big5 编码,而网页是 UTF-8 显示,则可以在<script>上使用charset指定.js的编码为 Big5:

<script type="text/javascript" charset="Big5" src="js/hello.js"></script>

默认情况下,浏览器会同步地下载 .js 文件,直到 .js 下载完成,并执行完内容之前,后续的其他资源下载、页面解析等都会被阻断。

可以在<script>加上async属性,如此浏览器会以非同步方式下载 .js 文件,在 .js 下载完成前,不会阻断后续资源的下载与页面解析,然而 .js 下载完成后,浏览器会暂停其他资源下载或页面解析,先执行该 .js 的内容后,再继续处理其他资源下载或页面解析,如果有多个async属性的 .js,执行的顺序是无法预期的。

可以在<script>加上defer属性,如此浏览器会以非同步方式下载 .js 文件,.js 就算下载完成,也不会马上执行,而是在 DOM 树生成与其他非defer的 .js 执行完后,才执行被加上defer属性的 .js,如果有多个defer属性的 .js,那么按照它们在页面上出现的顺序执行。

现在不支持 JavaScript 的浏览器几不存在,不过浏览器上的 JavaScript 仍可能因一些原因无法使用(例如防毒软件、安全机制等级,或者是爬虫程序之类)。如果想在无法执行 JavaScript 时,仍可呈现一些基本功能画面,则可以使用<noscript></noscript>,夹杂在<noscript></noscript>中的内容,会在无法执行 JavaScript 时出现,为使用者提供替代的页面内容。

有些浏览器或爬虫无法执行 JavaScript,此时会使用<!---->注解,让这些它们看不到 JavaScript 代码:

<script type="text/javascript">
<!--

    // 你的程序...

//-->
</script>

浏览器作为客户端的时候作了些调整,让<!--的作用如同 JavaScript 的//单行注解,所以<!--不会发生执行错误,而-->前的//因为是单行注解,所以就看不到之后的-->了。


展开阅读全文