zoukankan      html  css  js  c++  java
  • 初探内联方式的 onload="doSomething()"为何要加"()"?而js代码的 onload="doSomething" 和 addEventListener 为何不加"()"?

             

    • 问题引入:在看《Jquery基础教程》第四版的时,P34页有这样一段话

    引用函数与调用函数

      这里在将函数指定为处理程序时,省略了后面的圆括号,只使用了函数名。如果带着圆括号,函数会被立即调用;没有圆括号,函数名就只是函数的标识符或函数的引用,可以用于在将来再调用函数。

    这引发了我对于绑定事件方式的思考。我们都知道为元素绑定事件处理程序的时,内联方式要这样写 <body onload="doSomething();">...</body> ,或者javascript代码要这样写

    1 window.onload=doSomething;//或下一行的方式
    2 window.addEventListener('load',doSomething,false);
    3 function doSomething(){
    4     ...
    5  }

    我们一直都是这样用,但是有没有思考过为什么内联方式的 onload="doSomething()" 要加"()"?我给它不加可以吗?,而js代码的 onload 和 addEventListener 为什么不加"()",我给它加上可以吗?

    • 问题思考:如上面书里所说加"()"是调用函数,js代码执行到那一行时函数会被立即调用并执行。不加"()"是引用函数, window.onload 属性只是指向 doSomething 函数体(为什么说是指向而不是将简单的函数体赋值给onload属性待会验证),待将来触发了 onload事件,doSomething才会被加到任务队列等待主函数将它执行。
    • 问题验证

         1.标准内联方式,控制台会如约输出"test"。

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <title></title>
     5 </head>
     6 <body onload="doSomething()">
     7 <script type="text/javascript">
     8   function doSomething(){
     9     console.log('test');
    10   }
    11 </script>
    12 </body>
    13 </html>

         2.内联方式不加"()"

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <title></title>
     5 </head>
     6 <body onload="doSomething">
     7 <script type="text/javascript">
     8   function doSomething(){
     9     console.log('test');
    10   }
    11 </script>
    12 </body>
    13 </html>

    结果控制台不输出也没提示出错,来打断点看看程序到底发生了什么,给主要代码每行都打上断点

    然后重新运行程序,程序到第6行,暂停。

    点击继续执行,程序并没有执行第9行的代码而是运行直接完毕。然后再看下 document.body.onload 属性输出是

    所以这就意味着当 onload 事件触发时,去执行 function onload ,该函数内容是 doSomething 啊并不是 doSomething() ,所以 onload 事件触发后不会执行 doSomething 函数只是触发后进入 function onload 就结束了。

       3.标准js绑定事件方式, window.onload 和 addEventListener 方式一样,这里用前者举例,也会如约输出"test"

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4 <title></title>
     5 </head>
     6 <body>
     7 <script type="text/javascript">
     8   window.onload=doSomething; 
     9   function doSomething(){
    10     console.log('test');
    11   }
    12 </script>
    13 </body>
    14 </html>

      4. js代码换成 doSomething() ,仍然完美输出"test"且没报错,来分析一下

     1 <!DOCTYPE html>
     2 <html>
     3 <head>
     4   <title></title>
     5 </head>
     6 <body>
     7 <script type="text/javascript">
     8   window.onload=doSomething();
     9   function doSomething(){
    10     console.log('test');
    11   }
    12 </script>
    13 </body>
    14 </html>

    第8行断点,因为还没执行所以 window.onload=null ,这没有什么疑问, window 对象本身就给这些属性赋值为 null 。继续,

    .

    来到了第10行断点,准备执行 console ,这时在看 window.onload 怎么还是 null ?莫慌继续看,

    经过第10行断点,如约输出"test"没问题,查看 window.onload 还是 null ,直到运行完函数,最后查看 window.onload 依旧是 null ,这个时候会产生疑问是不是由于 doSomething 没有返回明显的值 window.onload 最后才会是null。测试一番

    确实是这样的(注:测试过 return 1;return "str"; 都不行,只能 return 对象类型)。

    这一系列测试足以说明以下代码完成的功能

    1 window.onload=doSomething();
    2 function doSomething(){
    3      console.log('test');
    4 }

    其实就是调用函数并执行然后返回值赋值变量,和注册事件并没啥关系。

    • 最后说说前面留的这个问题:window.onload属性只是指向doSomething函数体(为什么说是指向而不是将简单的函数体赋值给onload属性):

           

    给 window.onclick 添加属性 b=1 , window.onchange.b 输出也是1,足以说明确实是指向而不是赋值

  • 相关阅读:
    距离的总和
    [leetcode] 397. Integer Replacement
    [leetcode] 396. Rotate Function
    [leetcode] 398. Random Pick Index
    [leetcode] 399. Evaluate Division
    [算法] get_lucky_price price
    Geoserver(一) Geoserver2.15.4配置发布arcgis切片
    Geoserver(二) geoserver配置mysql插件
    OpenLayers4地图实例-功能齐全
    OpenLayers Node环境安装运行构建-支持Vue集成OpenLayers
  • 原文地址:https://www.cnblogs.com/venoral/p/5178336.html
Copyright © 2011-2022 走看看