我希望有人可以向我解释为什么在浏览器中查看HTML时,下面的JavaScript / HTML会显示“门#2”:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script type="text/javascript">
function testprint() {
alert('door #1');
};
window.onload = testprint;
function testprint() {
alert('door #2');
};
testprint = function() {
alert('door #3');
};
</script>
<script type="text/javascript">
function testprint() {
alert('door #4');
};
</script>
</head>
<body>
</body>
</html>
由于在testprint
设置为window.onload
之前只发出声明testprint
,我希望window.onload
会导致'门#1'出现。实际上,onload导致'门#2'。请注意,无论是否包含testprint
的第一个声明,它都会执行此操作。
testprint
的第三和第四个声明使用不同的方式来分配函数,我试着看看它是否会覆盖window.onload
的行为同样是{{1}的第二个声明确实。它没。请注意,如果我将testprint
的第四个声明移动到第一个脚本块的末尾,它将由testprint
调用。
答案 0 :(得分:38)
函数声明是提升的主题,它们在解析时被评估,通过提升意味着它们可用于声明它们的整个范围,例如:
foo(); // alerts foo
foo = function () { alert('bar')};
function foo () { alert('foo');}
foo(); // alerts bar
第一次调用foo
将执行函数声明,因为在解析时它可用,第二次调用foo
将执行运行时中声明的函数表达式。
有关函数表达式和函数声明之间差异的更详细讨论,请检查this question和this article。
答案 1 :(得分:0)
#3不改变window.onload的原因是函数是通过引用调用的,而不是通过名称调用的。设置window.onload = testprint
后,它会将testprint
的当前值(由CMS解释的门#2)分配给window.onload
。稍后更改testprint
的值不会影响window.onload
的值。
门#4不会覆盖门#2(除非,正如您所说,将其移动到第一个脚本块),因为它位于不同的脚本块中,因此在第一个块完成后会对其进行解析。
答案 2 :(得分:-1)
函数testprint是页面的全局。 testprint = function ...指定一个变量,我不确定它的整个范围,但是我认为它没有像第一个那样添加到函数表字典中。