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

时间:2009-11-10 19:09:00

标签: 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>

由于在testprint设置为window.onload之前只发出声明testprint,我希望window.onload会导致'门#1'出现。实际上,onload导致'门#2'。请注意,无论是否包含testprint的第一个声明,它都会执行此操作。

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

3 个答案:

答案 0 :(得分:38)

函数声明是提升的主题,它们在解析时被评估,通过提升意味着它们可用于声明它们的整个范围,例如:

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

第一次调用foo将执行函数声明,因为在解析时它可用,第二次调用foo将执行运行时中声明的函数表达式

有关函数表达式和函数声明之间差异的更详细讨论,请检查this questionthis article

答案 1 :(得分:0)

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

门#4不会覆盖门#2(除非,正如您所说,将其移动到第一个脚本块),因为它位于不同的脚本块中,因此在第一个块完成后会对其进行解析。

答案 2 :(得分:-1)

函数testprint是页面的全局。 testprint = function ...指定一个变量,我不确定它的整个范围,但是我认为它没有像第一个那样添加到函数表字典中。