原文:http://dean.edwards.name/weblog/2009/03/callbacks-vs-events/

先看如下代码:

1 document.addEventListener("DOMContentLoaded", function() {
2   console.log("Init: 1");
3   DOES_NOT_EXIST++; // error
4 }, false);
5
6 document.addEventListener("DOMContentLoaded", function() {
7   console.log("Init: 2");
8 }, false);

你预期当页面加载后,console下会出现什么结果?

结果是这样的:

Init: 1Uncaught ReferenceError: DOES_NOT_EXIST is not definedInit: 2

重点在于: 两个事件监听函数都执行了.虽然在第一个事件监听函数中出现了错误,但并没有阻止第二个函数的执行.

问题来了.

接下来我们基于回调函数系统的代码.使用jQuery:

1 $(document).ready(function() {
2   console.log("Init: 1");
3   DOES_NOT_EXIST++; // error
4 });
5
6 $(document).ready(function() {
7   console.log("Init: 2");
8 });

此时你从console下看到了什么?没错,是这样:

Init: 1
Uncaught ReferenceError: DOES_NOT_EXIST is not defined

好吧,这意味着回调函数系统是极其脆弱的.一旦任何一个回调函数中抛出了异常,则余下的回调函数序列将不再执行.

在实际开发环境中,这意味着一个写得烂的插件可以令其他插件无法初始化.

Dojo与jQuery有相同的问题,而YUI包装了try/catch机制,它会让回调函数中的错误悄悄地被捕获:

1 YAHOO.util.Event.onDOMReady(function() {
2   console.log("Init: 1");
3   DOES_NOT_EXIST++; // this will throw an error
4 });
5
6 YAHOO.util.Event.onDOMReady(function() {
7   console.log("Init: 2");
8 });

所以你将在console看到如下结果:

Init: 1Init: 2

几近完美的初始化! 貌似没什么好担心的了,除了那些你看不到的错误.

那该如何解决呢?

下面的解决方案是这样的: 使用回调函数混合真正的事件调度.

我们可以触发一个自定义事件,并在该事件的监听函数中,迂回地执行回调函数.

因为每个事件处理程序都有它自己的上下文,所以,即便在事件处理函数内发生了错误,也不会影响到我们的回调函数系统了.

回调函数序列中的每一个函数都将被执行.

这里是代码:

 1 var currentHandler;
 2
 3 if (document.addEventListener) {
 4   document.addEventListener("fakeEvents", function() {
 5     // execute the callback
 6     currentHandler();
 7   }, false);
 8
 9   var dispatchFakeEvent = function() {
10     var fakeEvent = document.createEvent("UIEvents");
11     fakeEvent.initEvent("fakeEvents", false, false);
12     document.dispatchEvent(fakeEvent);
13   };
14 } else { // MSIE
15
16   document.documentElement.fakeEvents = 0; // an expando property
17
18   document.documentElement.attachEvent("onpropertychange", function(event) {
19     if (event.propertyName == "fakeEvents") {
20       // execute the callback
21       currentHandler();
22     }
23   });
24
25   dispatchFakeEvent = function(handler) {
26     // fire the propertychange event
27     document.documentElement.fakeEvents++;
28   };
29 }
30
31 var onLoadHandlers = [];
32 function addOnLoad(handler) {
33   onLoadHandlers.push(handler);
34 };
35
36 window.onload = function() {
37   for (var i = 0; i < onLoadHandlers.length; i++) {
38     currentHandler = onLoadHandlers[i];
39     dispatchFakeEvent();
40   }
41 };

这次,执行结果当然又是我们预期的了:

Init: 1Uncaught ReferenceError: DOES_NOT_EXIST is not definedInit: 2

转载于:https://www.cnblogs.com/fangzhaolee/p/3719384.html

回调函数与DOM事件相关推荐

  1. 【Unity3D】动画回调函数、动画事件、动画曲线

    1 动画回调函数 动画回调函数是指动画在开始时.执行中.结束时回调的函数,主要有:OnStateEnter.OnStateUpdate.OnStateExit.OnStateMove.OnStateI ...

  2. python实现回调函数,自定义事件

    最近一个项目,需要实现自定义事件,发现python对于事件好像没有一个非常标准的封装,或者是原语,下面是自己去实现的一个类似事件的方法,逻辑上参考了.net实现事件的方法,也就是特殊的委托. 1. p ...

  3. JavaScript高级day01-PM【对象、函数、回调函数、IIFE、this、关于语句分号问题、webstorm代码模板、复习】

    笔记.视频.源码:JavaScript(基础.高级)笔记汇总表[尚硅谷JavaScript全套教程完整版] 目   录 P7 07.尚硅谷_JS高级_对象 23:30 1. 什么是对象? 2. 为什么 ...

  4. 什么函数是回调函数?

    1.什么函数是回调函数? 1.你定义得 2.你没有调用 3.它最终执行了 2.常见的回调函数 1.dom事件操作函数 2.ajax请求回调函数 3.定时器回调函数 ......

  5. 了解js中什么是回调函数?

    回调函数 简言之 就是你自己定义的 没有调用 但是它最终执行了的函数 常见的回调函数有 dom事件回调函数 鼠标经过离开点击等 定时器回调函数 ajax请求回调函数 生命周期回调函数 <body ...

  6. JavaScript基础总结深入(数据类型、数据_变量_内存、对象、函数、回调函数、this)

    数据类型 1.分类 JavaScript 数据类型分为两大类,分别为:基本类型,又称为值类型:对象类型,又称为引用类型. 基本(值)类型 String:任意字符 Number:任意的数字 boolea ...

  7. 由c#事件监听、回调函数引发观察者模式

    由c#事件监听.回调函数引发观察者模式 事件监听: C#中的事件,可以简单的理解为类或者对象发生了一件事,并且把这件事通知给了其他的类或者对象,其他的类或者对象可以根据事件的消息有所反应. 这非常类似 ...

  8. “约见”面试官系列之常见面试题之第六十一篇之IE和DOM事件流(建议收藏)

    什么是"事件流"? 事件流描述的是从页面中接收事件的顺序 事件流的种类: 事件流主要分为三种 事件冒泡流(IE事件流):事件开始时由最具体的元素(文档中嵌套最深的那个节点)接收,然 ...

  9. DOM事件与jQuery事件的是非纠葛

    在javascript和JQuery之中,都有事件的处理方式,在我们编写程序实现某些功能的时候,我们会发现使用原生的DOM事件与JQuery中封装的事件都能实现同样的效果,那么也许我们会认为他们之间的 ...

最新文章

  1. UTRAN 的用户面和控制面
  2. openSUSE 11.2 中文输入法 SCIM 安装
  3. python官网支持货到付款吗_官网购买的iPhone12pro还没发货?试着用Python快速入手...
  4. python有必要学吗-Python这么火,要不要学?听听华为工程师怎么说...
  5. UEditor文本浏览器,引号加斜杠解决
  6. 开箱即用——用这个模板快速统筹企业车辆安排
  7. django 套vue 模板_Vue admin template + Django 快速进行Web开发
  8. 方法 注释_在IDEA中配置类和方法的文档注释
  9. c语言指针易错情况,C语言/C++从入门到精通之指针易错点总结
  10. linux c 获取文件数量
  11. 创建模式--辛格尔顿
  12. html 复制文本 点击复制按钮
  13. pycharm新建python文件快捷键_Pycharm快捷键
  14. 黑帽SEO研究之js快照劫持代码分析
  15. 银河麒麟操作系统常用问题及解决方法
  16. 返乡之路不容易之12306余票查询并给出备选方案v2
  17. 图像渲染测试软件,Arnold渲染器之aiImage(ai图像)着色器介绍及渲染测试
  18. iPad连android热点掉线,iphone热点总掉线怎么办?苹果手机保持热点不断开的方法...
  19. PS运动模糊+径向模糊+高斯模糊
  20. JS实现页面的自动滚动【自动阅读、JS小工具】

热门文章

  1. java直线函数_java实现顺序结构线性列表的函数代码
  2. jquery获取元素宽高
  3. 【若依(ruoyi)】树表代码生成
  4. Kubernetes基础学习(一)
  5. python360百科_python抓取360百科踩过的坑!
  6. 愚人节整人软件测试自学,2020愚人节整蛊整人攻略大全
  7. php+字符串去掉反斜杠,PHP如何去掉反斜杠?
  8. html5 coverflow,使用CSS+JS帮你实现苹果cover flow效果
  9. Azkaban通过API动态传递参数
  10. SpringBoot指定服务项目名