本文转自知乎貘吃馍香的回答

提问:刚入门不久,能力有限,这个问题我描述起来有点困难,只有劳烦各位大神细看了

我之前一直以为js底层存在类似下面这样的代码:

//给所有dom对象定义好onclick值为一个空函数
HTMLElement.prototype.onclick = function(){}; //给所有dom对象绑定默认点击回调函数:点击时都执行一次自己的onclick方法
[].map.call(document.all,function(item){
item.addEventListener('click',function(){
this.onclick();
});
});

然后我认为给同一个元素多次添加事件函数,会形成一个待执行的函数队列,那么onclick以后无论怎么赋值,执行顺序会相对固定。
然而有如下可运行的代码我又无法解释(请展开全部之后再阅读代码,避免混乱):

//改变onclick的函数。此时body['click']的事件队列第一个函数为alert(1);
document.body.onclick = function(){alert(1)} //body['click']事件队列里增加了alert(2);点击时依次执行alert(1)、alert(2)
document.body.addEventListener('click',function(){alert(2)}); //再改变onclick的函数。此时body['click']的事件队列第一个函数换为alert(3);
document.body.onclick = function(){alert(3)}

然后这时候点击body,先后顺序本应该是alert(3)、alert(2),实际却是alert(3)在后面?
为什么仅仅凭一个赋值操作改变了onclick的值就能导致事件执行的顺序变了呢?
是“队列”的思想错误了,还是onclick=xxx,不是我想的那么简单?

补充后续思考:

如果onclick赋值时有内部操作改变了执行函数的队列,那js为什么要这么做呢?


貘吃馍香

路过
不同浏览器不一定是这个结果
底层代码肯定不是JS

仅趴了机器上几年前最老的blink代码看了下
EventListenerMap 里靠的是 EventListenerVector
这玩意就是个 Vector
typedef Vector<RegisteredEventListener, 1>
这么搞的

onclick setting 时候是 vector->find 后没有对应 handle
再 append 进去的
再次 setting 时是 find 有
就先 remove 老的再 append
没见 Vector 有用到(定义过) replace 方法

所以(在这么实现的浏览器上)才有这种现象

最终还是轮子哥猜对了。

vczh

合理猜测:给onclick赋值的内部操作时,remove掉原来的,add上新的。

onclick = xxx这种赋值写法绑定事件的原理是什么?的更多相关文章

  1. 面试时被问到js的绑定事件,我居然不知道怎么回答。回来查了下,做个笔记

    事件绑定是几种方法 以下为例: <button id='btn'>click me</button> function Btn(){ alert('click'); } 1.直 ...

  2. JavaScript中给onclick绑定事件后return false遇到的问题

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. js绑定事件方法:addEventListener与attachEvent的不同浏览器的兼容性写法

    js的事件绑定方法中,ie仅仅支持attachEvent,而FF和Chrome仅仅支持addEventListener,所以就必须为这两个方法做兼容处理,原理是先推断attachEvent仅仅否为真( ...

  4. 原生JS事件绑定方法以及jQuery绑定事件方法bind、live、on、delegate的区别

    一.原生JS事件绑定方法: 1.通过HTML属性进行事件处理函数的绑定如: <a href="#" onclick="f()"> 2.通过JavaS ...

  5. JQuery在循环中绑定事件的问题详解

    JQuery在循环中绑定事件的问题详解 有个页面上需要N个DOM,每个DOM里面的元素ID都要以数字结尾,比如说 ? 1 2 3 <input type="text" nam ...

  6. jQuery delegate方法实现Ajax请求绑定事件不丢失

    给元素绑定click事件后 ,遇到一个问题:当执行一些ajax请求,再次调用此页面,里面的这个click事件就失效了 比如说:我的分页是一个ajax请求 但我点下一页时 后生成的元素a就没有了clic ...

  7. JavaScript绑定事件的方法[3种]

    在JavaScript中,有三种常用的绑定事件的方法: 在DOM元素中直接绑定: 在JavaScript代码中绑定: 绑定事件监听函数. 一. 在DOM元素中直接绑定 这里的DOM元素,可以理解为HT ...

  8. Xamarin.Android中使用android:onClick="xxx"属性

    原文:Xamarin.Android中使用android:onClick="xxx"属性 在原生Android开发中,为一个View增加点击事件,有三种方式: 1.使用匿名对象 ( ...

  9. dom元素循环绑定事件的技巧

    以前总觉得自己写的代码不太规范,尤其是写原生的时候.举个例子: 要为页面上所有".a"的元素绑定事件,当然了用jquery很方便:$('.a').bind("click& ...

随机推荐

  1. 用Less定义常用的CSS3效果函数及常用颜色搭配(让CSS写起来更有趣)

    定义圆角及调用 /* 定义圆角 @radius 圆角大小 */ .round(@radius:5px){ border-radius:@radius; -webkit-border-radius: @ ...

  2. Window下JDK安装与配置

    今天项目组开会,由于.Net平台的限制无法满足现有业务需求,项目计划从.Net平台转Java平台,采用Java+Spark+Hadoop,之前关于Java和Hadoop的书也买的有只是平时看的少,最近 ...

  3. JavaScript学习12 JS中定义对象的几种方式【转】

    avaScript学习12 JS中定义对象的几种方式 转自:  http://www.cnblogs.com/mengdd/p/3697255.html JavaScript中没有类的概念,只有对象. ...

  4. 1583: [Usaco2009 Mar]Moon Mooing 哞哞叫

    1583: [Usaco2009 Mar]Moon Mooing 哞哞叫 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 244  Solved: 126 ...

  5. Spring+SpringMVC+MyBatis+easyUI整合基础篇(十)SVN搭建

    日常啰嗦 前面一篇文章讲了一下版本控制,但其实这一篇并没有打算讲细节的,感觉应该自己去动手弄一下,后来考虑了一下,版本控制真的挺重要的,如果自己实在搭建不好反而不去使用的话,真的有点可惜,当然这些话是 ...

  6. 超出父视图无法点击问题hitTest

    p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 18.0px Menlo; color: #c91b13 } p.p2 { margin: 0.0px 0. ...

  7. UITextField输入限制/小数/首位等

    - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementS ...

  8. js实现ajax的post请求步骤

    post请求步骤与前篇的get请求步骤差别不大,只是增加了 xhr.setRequestHeader("Content-type","application/x-www- ...

  9. 【Javascript】搞定JS面试——跨域问题

    什么是跨域? 为什么不能跨域? 跨域的解决方案都有哪些(解决方法/适用场景/get还是post)?  一.什么是跨域?       只要协议.域名.端口有任何一个不同,就是跨域.           ...

  10. Django REST framework使用ViewSets的自定义路由实现过程

    在Django中使用基于类的视图(ClassView),类中所定义的方法名称与Http的请求方法相对应,才能基于路由将请求分发(dispatch)到ClassView中的方法进行处理,而Django ...