script标签位置放错报错

关于<script>在HTML中的位置问题

今天在做Ajax发送POST请求实验时遇到了一个由于<script>位置放错导致的错误。
代码如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>AJAX发送请求</title>
</head>

<script>	
	var btn = document.getElementById("btn");
	var textusername = document.getElementById("username");
	var textpassword = document.getElementById("password");
	
	btn.onclick = function(){
		
		//获取界面上的元素value
		var username = textusername.value;
		var password = textpassword.value;
		
		//通过XMLHttpRequest发送POST请求
		var xhr;
		xhr = new XMLHttpRequest();
		xhr.open("POST","LoginServlet");
		//如果请求体是urlencoded格式,必须设置这个请求头
		xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
		xhr.send("username=" + username  + "& password=" + password);
		xhr.onreadystatechange = function(){
			if(this.readyState != 4) return;
			document.getElementById("result").innerHTML = xhr.responseText;
		}
	}
</script>

<body>
<table border="1">
	<tr>
		<td>用户名</td>
		<td><input type="text" id="username" name="username"></td>
	</tr>
	<tr>
		<td>密码</td>
		<td><input type="password" id="password" name="password"></td>
	</tr>
	<tr><td><button type="button"  id="btn">登录</button></td>
		<td><label id="result"></label></td></tr>
	
</table>
</body>
</html>

结果:浏览器控制台报错Uncaught TypeError:Cannot set prioerty ‘onclick’ of full
浏览器控制台报错
解决方案:百度说是<script>位置的问题,于是试着把<script>代码块的内容放到了</body>标签之后,结果没有报错了。

问题所在:这里的<script>脚本需要访问到dom元素,但此时还未生成dom元素,所以报错。

原理: HTML是自上而下加载页面的,但引入的css和javascript的顺序有所不同,css引入执行加载时,程序仍然往下执行,而执行到<script>脚本时则中断线程,待该script脚本执行结束之后程序才继续往下执行。

<script>应该放在HTML的什么位置呢?(由百度和知乎所得)

  1. 对于必须在DOM加载之前运行的脚本,放在<head>标签中。但要确保内敛的这些脚本很小,最好是压缩过的,并且执行速度很快,不会造成浏览器渲染的阻塞。
  2. 对于需要访问DOM的脚本,放在<body>标签中。
  3. 使用<script>标签的asyncdefer属性。
  • async实现脚本的异步加载(仅适用于外部脚本,即使用src属性时),不会阻塞浏览器对页面的渲染,但带有async属性的脚本不能保证它们执行的前后顺序。
    下面是摘自W3school的例子:
<!DOCTYPE html>
<html>
<body>

<p id="p1">Hello World!</p>
<script type="text/javascript" src="/example/html5/demo_async.js" async="async"></script>

</body>
</html>
  • defer实现脚本的延时加载(仅适用于外部脚本,即使用src属性时),脚本会被延迟至整个页面解析完成后再执行。
    下面是摘自W3school的例子:
<html>
<body>

<script type="text/javascript" defer="defer">
alert(document.getElementById("p1").firstChild.nodeValue);
</script>

<p>上面的脚本会从下面的段落中请求信息。通常,这是做不到的,因为在段落加载之前,脚本已经运行过了。</p>

<p id="p1">Hello World!</p>

<p>然而,defer 属性规定了脚本必须在页面加载完毕后执行。这样,脚本就可以从段落中请求数据了。</p>

<p><b>注释:</b>该属性只能在 Internet Explorer 中运行。</p>

</body>
</html>

关于 <script>放在<body>结束标签之后<html>标签之前 还是 <body>结束标签之前
测试发现这两种方法的结果都没有区别。根据HTML5标准中出现的HTML语法规则,如果在</body> 后再出现<script>或任何元素的开始标签,都是parse error,浏览器会忽略之前的</body>,即视作仍旧在body内,最终的DOM树里,<script>元素还是会成为body的子节点。虽然把<script>放在<body>结束标签之后<html>标签之前也没报错,但是这不符合标准,而且没有带来任何好处,所以不建议这样做。

参考文章:
为什么把 Script 标签放在 body 结束标签之后 html 结束标签之前?
该把JS文件放在HTML文档的那个位置

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值