引入JavaScript的两种方法
引入JavaScript主要又两种方法,者两种方法都需要使用到<script>标签。这个标签最早由Netscape Navigator创造,不过早已成为了HTML正式规范。
在页面中嵌入JavaScript代码
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JavaScript的引入</title>
</head>
<body>
<script>
var a=1;
alert(a);
</script>
</body>
</html>
引入外部文件
可以通过<script>标签的src属性引入外部js文件。
虽然<script>标签还有这许多其他属性,但是这些属性都不常用,或者都有着默认值,而这些默认值通常都无需更改,所以src属性可能是你唯一需要了解的属性。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JavaScript的引入</title>
</head>
<body>
<!-- 引入本地文件 -->
<script src="./script.js"></script>
<!-- 引入外部域的文件 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</body>
</html>
这种方式服务器将会以MIME类型为application/x-javascript将JavaScript文件传送到浏览器。
JavaScript脚本的执行顺序以及作用域
被引入的JavaScript脚本将按照<script>标签的顺序逐个执行,并且它们共享一个全局作用域。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JavaScript的引入</title>
</head>
<body>
<script>
var a=1;
function sayHello(){
alert("hello");
}
alert(b);//控制台会报错,因为此时b尚未声明
</script>
<script>
//可以成功地使用变量a和函数sayHello()尽管它们定义在不同地script中
//但运行时它们时共享同一个作用域地
alert(a);
sayHello();
var b=2;//此时声明地变量b在前面是无法使用的,因为JavaScript是按照script便签的顺序逐行执行
</script>
</body>
</html>
弄清楚作用域问题很重要,因为这个问题在长期一来都是困扰前端开发的重大问题,想象一下:当页面使用了不同的开发人员写的脚本时谁能保证代码中没有重名的变量和函数呢?由于它们共享一个作用域重名的变量将会相互覆盖这将导致一场灾难。
<script>标签的位置
<script>标签不仅可以在<body>中也可以出现在<head>中:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JavaScript的引入</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
</body>
</html>
<script>标签出现在哪并无规定,但是你要记住,页面渲染的时候时按照<script>标签出现的顺序执行的,也就是说如果<script>标签如果出现在<body>的前面,那么浏览器只有当将所有的<script>便签下载并执行完毕才会渲染<body>元素中的文档内容。
一个简单的实验
已知alert()方法会阻塞程序的执行,
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JavaScript的引入</title>
<script>
alert("hello");
</script>
</head>
<body>
<h1>引入JavaScript</h1>
</body>
</html>
当你将页面拖拽到浏览器将会是这样:
可以看到背面的文档内容空空如也,因为当执行到<script>中的alert()时程序已经阻塞了,此时还没有渲染页面内容。
可想而知,如果此时在<script>中直接操作DOM时不可行的,因为此时DOM尚未创建!
现在稍作修改:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JavaScript的引入</title>
</head>
<body>
<h1>引入JavaScript</h1>
<script>
alert("hello");
</script>
</body>
</html>
再次拖拽:
可以看到此时背景中的文档已经渲染完毕。这就是这两中方法最主要的区别。
<noscript>标签
与<script>标签相对,<noscript>标签将会在浏览器不支持JavaScript时呈现出里面的内容。这个标签通常用来做一些平稳退化,尽管现在所有的浏览器都已经支持JavaScript,但是你不能保证没有奇葩的用户关闭了浏览器的JavaScript功能:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>JavaScript的引入</title>
</head>
<body>
<noscript>
<h1>本页面需要使用JavaScript,请打开相应功能</h1>
</noscript>
<h1>引入JavaScript</h1>
</body>
</html>
总结
- 可以使用<script>标签嵌入JavaScript或者引入外部文件
- <script>出现的位置需要格外注意,以避免JavaScript操作尚未渲染的文档或者覆盖已经渲染好的文档
- 可以使用<noscript>标签提示用户打开浏览器脚本功能