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

Referencing a JavaScript value before it is declared - can someone explain this

我希望有人能向我解释,当在浏览器中查看HTML时,下面的javascript/html为什么会显示"door 2":

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!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 type="text/javascript">
        function testprint() {
            alert('door #4');
        };
   
</head>
<body>
</body>
</html>

由于只有声明testprint发生在window.onload设置为testprint之前,我希望window.onload导致‘门1’出现。实际上,onload会导致"门2"。请注意,无论是否包括testprint的第一个声明,它都会这样做。

EDOCX1的第三个和第四个声明使用了不同的方法来分配函数,我尝试了这个方法来看看它是否会覆盖EDOCX1的行为,同样的,EDOCX1的第二个声明(0)也会。它没有。注意,如果我将EDOCX1的第四个声明(0)移动到第一个脚本块的末尾,它将由window.onload调用。


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

1
2
3
4
foo(); // alerts foo
foo = function () { alert('bar')};
function foo () { alert('foo');}
foo(); // alerts bar

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

有关函数表达式和函数声明之间的区别的更详细的讨论,请检查这个问题和本文。


3不更改window.onload的原因是函数是通过引用调用的,而不是通过名称调用的。当设置window.onload = testprint时,它会将testprint的当前值(门2,如cms所解释的那样)指定给window.onload。以后改变testprint的值并不影响window.onload的值。

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


函数testprint是该页的全局函数。testprint=函数…分配一个变量,我不确定它的整个范围,但我得到了这样的想法:它不会像第一个变量那样添加到函数表字典中。