在声明之前引用JavaScript值 – 有人可以解释这一点

我希望有人能向我解释为什么当在浏览器中查看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> 

由于在window.onload设置为testprint之前只有声明testprint ,所以我期望window.onload原因'door#1'出现。 其实,onload会导致“2号门”。 请注意,无论是否包含testprint的第一个声明,都testprint

testprint的第三个和第四个声明使用不同的方式来分配函数,我试着看看它是否会覆盖window.onload的行为,同样是testprint的第二个声明。 它没有。 请注意,如果将testprint的第四个声明移动到第一个脚本块的末尾,它将被window.onload调用。

函数声明是提升的对象,并且在parsing时被评估,通过提升意味着它们可以被声明在整个范围内,例如:

 foo(); // alerts foo foo = function () { alert('bar')}; function foo () { alert('foo');} foo(); // alerts bar 

foo的第一个调用将执行函数声明 ,因为在parsing时它是可用的, foo的第二个调用将执行在运行时声明的函数expression式

有关函数expression式和函数声明之间差异的更详细的讨论,请查看这个问题和这篇文章 。

原因#3不会改变window.onload是函数被引用调用,而不是名称。 当您设置window.onload = testprint ,它将对testprint的当前值(门#2,如CMS所解释)分配给window.onload 。 稍后更改testprint的值不会影响window.onload的值。

4号门不会覆盖2号门(除非,如你所说,将其移动到第一个脚本块),因为它位于不同的脚本块中,所以在第一个块完成之后将被parsing。

函数testprint是全局的页面。 testprint = function …指定了一个variables,我不能确定整个范围,但是我发现它并没有像第一个那样添加到函数表字典中。