日期:2014-05-16  浏览次数:20358 次

关于伪协议javascript:

前几天有人问我为什么点击链接后页面变成了一个只有“false”的页面,我猜想大概是滥用了javascript:伪协议吧。最终因为没让我看出事的代码,真正原因也就不得而知。不过我借此契机理清了此处疑惑,倒也算有所得了。

?

一般说来,伪协议经常被用到<a>的href属性上,例如<a href="javascript:alert('hello');">。这样,点击此链接的默认行为就是弹出一个框,而不是跳转至某页面了。此处需要注意的地方有两点:

1,返回值对浏览器行为的影响。返回undefined,停留在原页面,其它跳转至返回值。这就是为什么出现“false”页面的原因了。旧代码中能看到javascript:void(...);的写法,其实也是为了生成一个undefined的返回值,等同于在最后直接加return;。

2,this指向global变量。这不是说例子中alert里的this是global变量,而是连href属性里的this是global变量。因为此处是默认行为,不是事件,所以里面的代码的执行上下文不是触发元素。

?

伪协议还可以使用在form元素的action里,行为和使用在anchor上一样。至于其它地方可不可以使用,或者有没有什么其它细节之类的,我就觉得没有了解的必要了,毕竟这是一种已经不推荐使用的技术了,即混淆了结构又没有适当的fallback。

?

附上测试的代码,我觉得能运行的代码往往说明的能力更强。

<!DOCTYPE html>
<html>
<head>
  <title>My Test Page</title>
</head>
<body>
	<div>
		<form id="f" action="javascript:alertThis(this, 'action');" onsubmit="alertThis(this, 'submit');">
			<div><input type="submit" value="Empty form" /></div>
		</form>
		<a href="javascript:alertThis(this, 'anchor');" onclick="alertThis(this, 'click');">empty anchor</a>
	</div>
</body>
<script type="text/javascript">
var logger = typeof(console) === 'object' ? console : {};
if (!logger.log) logger.log = alert;
function alertThis() {
	logger.log("this is " + this + "\nargs[0] is " + arguments[0] + "\nargs[1] is " + arguments[1]);
}
</script>
</html>
?