V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
kuanng
V2EX  ›  程序员

请教大家,一个我偶然发现的关于 JS 事件处理的小问题

  •  
  •   kuanng · 2019-04-21 18:55:33 +08:00 · 1915 次点击
    这是一个创建于 1821 天前的主题,其中的信息可能已经有所发展或是发生改变。

    我给 div 绑定一个 click 事件,代码如下:

    <div onclick="click()"></div>
    
    <script>
      function click() {
        console.log('click')
      }
    </script>
    

    单击触发 click 事件,运行结果如下:

    我发现控制台没有任何的输出,第一时间我检查了一下代码,看上去好像没有任何问题呀。

    突然想到, [难道 handle 函数的名字不能为 click ?] 我试着修改为 myclick,修改后代码如下:

    <div onclick="myclick()"></div>
    
    <script>
      function myclick() {
        console.log('click')
      }
    </script>
    

    重新运行,结果如下:

    居然真的可以,难道 handle 函数名不可以和事件名相同? js 中还有这样的规定? [心想,我 js 基础太差了吧]

    我开始实验其他事件是不是也有相同的规定,所以我将 click 事件修改为 dblclick 事件,代码如下:

    <div ondblclick="dblclick()"></div>
    
    <script>
      function dblclick() {
        console.log('dblclick')
      }
    </script>
    

    双击触发事件,结果如下:

    居然可以 log 出来? [不是说好的 handle 函数名不能和事件名相同么?] 什么情况???

    接下来我测试了 mousedown, mouseup, keyup, keydown, keypress 事件,都可以 log 出来,这就不上图了。

    凭直觉, [应该只有 click 事件处理函数名不能为 click ] ,但这是为什么呢?

    我加断点调试再次确定了没有执行 script 中的 click 处理函数。

    我分析名为 click 的事件处理函数没有被调用的原因,难道是被覆盖了?

    如果是这样的话,那么我应该可以 console.log(click) ,代码如下:

    <div onclick="console.log(click)"></div>
    

    运行结果如下:

    显而易见这样写是不可以的:

    <div onclick="myclick()"></div>
    
    <script>
      function myclick() {
        console.log(click)  //ReferenceError: click is not defined
      }
    </script>
    

    [果然是本地函数 click 覆盖了名为 click 的处理函数] ,但是随意想想,什么情况?有全局 click 函数???

    下面就是让我感到不解的地方。

    • 第一:既然可以在 dom 元素中 onclick="console.log(click)" ,并且没有类似于 window.Array === Array //true 等本地函数,因为 window.click //undefinded。那么这个 click 究竟被谁引用着?或者说为什么只有内联 js 才可以 console.log(click) 。

    • 第二:我测试了下面的代码:

    <div onclick="console.log('click'); click()"></div>
    

    运行结果如下:

    难道执行了两次 onclick 中的代码?

    试着再调用一次 click(),代码如下:

    <div onclick="console.log('click'); click(); click()"></div>
    

    看出来了规律:

    但是怎么解释这个运行结果?这也没有递归啊,js 引擎是怎么执行这段代码的?

    • 第三:在假设 [只有 click 的事件 handle 函数名不能为 click ] 的条件成立,那么为什么只有 click 事件是特殊的?为什么不能是其他事件?

    希望大家可以解决这个问题!

    环境:win10 + chrome

    12 条回复    2019-04-22 14:37:11 +08:00
    rabbbit
        1
    rabbbit  
       2019-04-21 19:12:36 +08:00
    <div onclick="console.log(this.click === click);console.log(event.currentTarget.click === click)"></div>
    Mutoo
        2
    Mutoo  
       2019-04-21 19:15:35 +08:00   ❤️ 3
    我之前遇到过 <form onsubmit="submit()"></form> 也遇到类似的问题。

    在 onclick 这个 DOM Level 0 的事件侦听器上,存在一个默认的 With Block 作用域指向元素本身(这里的 this 即 div ),于是这里的 click 方法指向的是 div.click() (优先级更高)而不是 window.click()

    如果你用 DOM Level 3 的事件侦听器:div.addEventListener('click', ...) 则不会有这个问题。
    ayase252
        3
    ayase252  
       2019-04-21 19:27:18 +08:00   ❤️ 1
    Biwood
        4
    Biwood  
       2019-04-21 19:34:28 +08:00 via Android   ❤️ 4
    当使用 attribute 来绑定事件时,handler 的 this 指向元素本身,也就是 div 元素,所以 click()也相当于 div.click()。
    为什么其他事件名不行?因为 div 是由 HTMLDivElement 接口实现的,而它又继承自 HTMLElement,click 属于该接口的一个 method,而 dblclick 则不是。
    请参考 https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement#Methods
    kuanng
        5
    kuanng  
    OP
       2019-04-21 19:58:45 +08:00
    @Biwood 学到了,感谢!
    kuanng
        6
    kuanng  
    OP
       2019-04-21 20:01:06 +08:00
    @Biwood 请问第二个问题的代码为什么不以递归的方式一直执行?
    Biwood
        7
    Biwood  
       2019-04-21 20:13:06 +08:00 via Android   ❤️ 1
    @kuanng 浏览器的安全策略,第二轮递归中的 div.click 不是由人类行为直接触发,会被浏览器阻止。
    kuanng
        8
    kuanng  
    OP
       2019-04-21 22:33:00 +08:00
    感谢大家的回复!
    meepo3927
        9
    meepo3927  
       2019-04-22 11:23:23 +08:00
    很涨姿势
    buhi
        10
    buhi  
       2019-04-22 11:32:05 +08:00
    很偏门的姿势呢 学习了
    longjiahui
        11
    longjiahui  
       2019-04-22 13:59:23 +08:00
    完全没试过直接用 click 命名的。 🧱
    zhw2590582
        12
    zhw2590582  
       2019-04-22 14:37:11 +08:00
    涨姿势了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3979 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 10:29 · PVG 18:29 · LAX 03:29 · JFK 06:29
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.