为何JavaScript脚本分段放置会报错?求解析执行逻辑
理解JavaScript运行逻辑:HTML解析顺序与变量提升
你遇到的问题核心是混淆了两个关键机制:HTML中<script>标签的执行顺序,以及单个<script>标签内的JavaScript预编译(变量提升)规则。下面逐个拆解你的三个场景:
场景1:head中定义函数,body中调用正常运行
浏览器解析HTML是从上到下顺序执行的,<head>里的<script>会先于<body>里的代码执行。当<body>里的<script>调用say_hello时,这个函数已经在全局作用域中被定义完成,所以可以正常执行。
<!DOCTYPE HTML> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script> function say_hello() { document.write('hello'); } </script> </head> <body> <script> say_hello(); </script> </body> </html>
场景2:调用脚本在定义脚本之前,报错
同样遵循HTML从上到下的执行顺序,第一个<script>执行时,第二个<script>还没被解析执行,say_hello函数还未被定义,自然会抛出引用错误。
<!DOCTYPE HTML> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <script> say_hello(); </script> <script> function say_hello() { document.write('hello'); } </script> </body> </html>
场景3:同一<script>内先调用后定义,正常运行
单个<script>标签内的JavaScript代码执行前,引擎会先进行预编译:所有函数声明会被提升到当前作用域的顶部。也就是说,虽然你写代码时先调用后定义,但实际执行顺序是先定义函数,再执行调用语句,所以不会报错。
<!DOCTYPE HTML> <html lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <script> say_hello(); function say_hello() { document.write('hello'); } </script> </body> </html>
关于脚本放在body末尾的正确实践
把脚本放在body末尾是为了避免操作未加载的DOM,但要注意:
- 如果拆分多个
<script>标签,被调用的函数必须在调用代码所在的<script>之前执行(即放在前面的<script>里) - 如果是同一
<script>内的代码,函数声明的提升机制可以让你在定义前调用,但变量声明的提升有区别(比如var声明的变量会提升但未初始化,let/const则会形成暂时性死区)
内容的提问来源于stack exchange,提问作者bookworm
相关产品推荐
相关产品推荐

