【问题标题】:Why javascript function in the body takes precedence over function in the head?为什么正文中的 javascript 函数优先于头部中的函数?
【发布时间】:2018-06-03 04:49:47
【问题描述】:

我试图了解 javascript 中的执行顺序。为什么body中的foo优先于head中的foo。不是先编译的head里的foo吗?

<head>
  <meta charset="UTF-8">
  <title>Hello</title>

  <script type="text/javascript">
    function foo() {
      greeting = "hello from the head";
      alert(greeting);
    }
  </script>
</head>

<body>
  <div id="clickMe" onclick="foo()">Click me</div>
  <script>
    function foo() {
      greeting = "hello from the body";
      alert(greeting);
    }
  </script>
</body>

</html>

【问题讨论】:

    标签: javascript function execution


    【解决方案1】:

    以后的函数声明会覆盖旧的函数声明。在新函数被声明之前,旧函数仍然可以被调用:

    <script type="text/javascript">
      function foo() {
        greeting = "hello from the head";
        alert(greeting);
      }
      foo();
    </script>
    <div id="clickMe" onclick="foo()">Click me</div>
    <script>
      function foo() {
        greeting = "hello from the body";
        alert(greeting);
      }
    </script>

    但是一旦较低的脚本标签运行,函数名就会被重新分配。如果你这样看可能更有意义,每个函数都重新分配window.foo

    <script type="text/javascript">
      window.foo = function foo() {
        greeting = "hello from the head";
        alert(greeting);
      }
    </script>
    <div id="clickMe" onclick="window.foo()">Click me</div>
    <script>
      window.foo = function foo() {
        greeting = "hello from the body";
        alert(greeting);
      }
    </script>

    【讨论】:

    • Javascript 未被解释。它有一个运行时编译器。
    【解决方案2】:

    这与两次声明同一个函数没有什么不同

    function foo() {
      console.log("first");
    }
    
    function foo() {
      console.log("second");
    }
    
    foo();  // prints "second"

    这在某种程度上与此没有什么不同

    let bar;
    bar = 1;
    bar = 2;
    

    bar 现在是2

    您可以通过使用不同的语法来避免这种情况

    const foo = () => {
      console.log("first");
    };
    
    const foo = () => {
      console.log("second");
    };

    在这种情况下你会得到一个错误

    Uncaught SyntaxError: Identifier 'foo' has already been declared
    

    而且似乎可以跨脚本工作

    <script>
    const foo = () => {
      console.log("first");
    };
    </script>
    <script>
    const foo = () => {
      console.log("second");
    };
    </script>

    【讨论】:

      【解决方案3】:

      这就是所谓的影子。

      JS 编译器提升脚本中的函数。后面的会用相同的名字覆盖前面的遭遇。

      function foo() {
         console.log('Foo early');
      }
      
      function foo() {
         console.log('Foo late');
      }
      
      foo();    //Foo leate
      

      【讨论】:

      • 这不是阴影。不同之处在于阴影意味着仍然存在对原始定义的引用。
      • 阴影如何引用原始定义?能举个例子吗?
      • var array = []; array.map = () =&gt; {}; array.map(); /* returns undefined */ delete array.map; array.map(() =&gt; {}); /* returns array */ 这使用原型链来隐藏 map() 的定义。在HTMLInputElement 上使用具有相同名称的 DOM 元素属性和属性时存在类似的示例,例如 value
      • 那是属性阴影。虽然这是真的,但它并没有使 OP 的案例不被遮蔽。后面的声明会影响前面的提升函数。
      • “属性阴影”,不管你喜欢怎么称呼它,仍然存在于顶级函数声明中,它只是window 的一个自己的属性。例如function addEventListener () {} 会影响window.addEventListener,因为它不是window 自己的属性,但function prompt () {} 会覆盖window.prompt,因为它 window 的自己的属性
      【解决方案4】:

      基本上只是因为主体中的那个是它读取的最后一个函数,所以它只是坚持下去。

      记住 HTML 文档是从上到下读取的,所以如果你有两个相同函数的实例,它实际上会保留最接近文档末尾的那个

      【讨论】:

        猜你喜欢
        • 2018-10-31
        • 1970-01-01
        • 2012-06-11
        • 2021-08-15
        • 2014-09-27
        • 2015-11-15
        • 2019-04-14
        • 1970-01-01
        • 2012-09-26
        相关资源
        最近更新 更多