请教大家,一个我偶然发现的关于 JS 事件处理的小问题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
kuanng

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

  •  
  •   kuanng 2019 年 4 月 21 日 2417 次点击
    这是一个创建于 2561 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

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

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

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

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

    <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 年 4 月 21 日
    <div Onclick="console.log(this.click === click);console.log(event.currentTarget.click === click)"></div>
    Mutoo
        2
    Mutoo  
       2019 年 4 月 21 日   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 年 4 月 21 日   1
    Biwood
        4
    Biwood  
       2019 年 4 月 21 日 via Android   4
    当使用 attribute 来绑定事件时,handler 的 this 指向元素本身,也就是 div 元素,所以 click()也相当于 div.click()。
    为什么其他事件名不行?因为 div 是由 HTMLDivElement 接口实现的,而它又继承自 HTMLElement,click 属于该接口的一个 method,而 dbclick 则不是。
    请参考 https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement#Methods
    kuanng
        5
    kuanng  
    OP
       2019 年 4 月 21 日
    @Biwood 学到了,感谢!
    kuanng
        6
    kuanng  
    OP
       2019 年 4 月 21 日
    @Biwood 请问第二个问题的代码为什么不以递归的方式一直执行?
    Biwood
        7
    Biwood  
       2019 年 4 月 21 日 via Android   1
    @kuanng 浏览器的安全策略,第二轮递归中的 div.click 不是由人类行为直接触发,会被浏览器阻止。
    kuanng
        8
    kuanng  
    OP
       2019 年 4 月 21 日
    感谢大家的回复!
    meepo3927
        9
    meepo3927  
       2019 年 4 月 22 日
    很涨姿势
    buhi
        10
    buhi  
       2019 年 4 月 22 日
    很偏门的姿势呢 学习了
    longjiahui
        11
    longjiahui  
       2019 年 4 月 22 日
    完全没试过直接用 click 命名的。
    zhw2590582
        12
    zhw2590582  
       2019 年 4 月 22 日
    涨姿势了
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2484 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 52ms UTC 01:08 PVG 09:08 LAX 18:08 JFK 21:08
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86