解决 window.onload 被覆盖的问题方法


Posted in Javascript onJanuary 14, 2020

手头在维护一个比较老的项目,由于页面的重组,一些不同页面的 js 被加载到了同一个页面,导致一个页面里可能有一个以上的 window.onload ,这样做的后果就是前面的回调函数会被后面的覆盖掉。
上网搜了一下,绝大部分的解决方案有两种:

  1. 重载 window.onload 方法;
  2. 呼吁使用 window.addEventListener 。

这两种方法要么只能预防,要么需要更改老代码。我的情况比较特殊,老代码是采用 webpack 打包过的,但是配置文件不见了,之前的维护人员直接修改了打包后的代码,导致重新打包的工作量巨大,只能慢慢来。

思前想后,决定利用 Object.defineProperty 劫持 window.onload 的赋值行为,把对应的回调函数放到一个队列中集中处理。

代码如下:

/**
 * @function windowLoadInit - 劫持 window.onload 的赋值行为,防止覆盖
 * @desc 函数调用前产生的覆盖不可逆转
 * @throw {Any} 所有回调执行完毕之后,会抛出 catch 到的第一个错误
 *  错误将被异步抛出,避免影响初始化函数的继续执行
 * @return {Function} 
 */
function windowLoadInit(){
 const eventQueue = [];
 
 // 防止覆盖之前的 window.onload
 window.onload instanceof Function && eventQueue.push(window.onload); 
 
 window.onload = e => {
  const errQueue = [];
  // 逐个处理回调事件
  while(!!eventQueue.length){
    try{
      eventQueue.shift()(e);
    } catch(err){
      errQueue.push(err);
    }
  }
  
  if(!!errQueue.length) {
    setTimeout(() => {
      throw errQueue.shift();
    },0);
  };
 };
 
 // 每次赋值时,将回调函数添加到队列
 Object.defineProperty(window, 'onload', { 
  set: eventQueue.push
 }); 
 
 return window.onload
}

测试代码:

// 此 testCase 需在页面加载完成前执行
function testCase(){
 const arr = [];
 window.onload = () => arr.push(-1); // 这个回调的覆盖不可避免
 window.onload = () => arr.push(0);
 windowLoadInit();
 window.onload = () => arr.push(1);
 window.onload = () => arr.push(2);
 
 return new Promise(resolve => {
  window.onload = () => resolve(arr.join('') === '012')
 })
}
testCase().then(console.log); // true

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
IE中直接运行显示当前网页中的图片 推荐
Aug 31 Javascript
javascript中的变量是传值还是传址的?
Apr 19 Javascript
javaScript复制功能调用实现方案
Dec 13 Javascript
JavaScript实现跑马灯抽奖活动实例代码解析与优化(一)
Feb 16 Javascript
基于zepto的移动端轻量级日期插件--date_picker
Mar 04 Javascript
jQuery Checkbox 全选 反选的简单实例
Nov 29 Javascript
AngularJS实现自定义指令及指令配置项的方法
Nov 20 Javascript
基于vue监听滚动事件实现锚点链接平滑滚动的方法
Jan 17 Javascript
JS高阶函数原理与用法实例分析
Jan 15 Javascript
深入理解vue中的slot与slot-scope
Apr 22 Javascript
layui表格内放置图片,并点击放大的实例
Sep 10 Javascript
记一次vue跨域的解决
Oct 21 Javascript
vue quill editor 使用富文本添加上传音频功能
Jan 14 #Javascript
JavaScript事件冒泡机制原理实例解析
Jan 14 #Javascript
JS window对象简单操作完整示例
Jan 14 #Javascript
让mocha支持ES6模块的方法实现
Jan 14 #Javascript
JavaScript遍历数组的方法代码实例
Jan 14 #Javascript
JavaScript回调函数callback用法解析
Jan 14 #Javascript
JS document对象简单用法完整示例
Jan 14 #Javascript
You might like
用PHP实现小型站点广告管理(修正版)
2006/10/09 PHP
PHP 导出数据到淘宝助手CSV的方法分享
2010/02/27 PHP
jquery基础教程之deferred对象使用方法
2014/01/22 Javascript
js实现完美兼容各大浏览器的人民币大小写相互转换
2015/10/29 Javascript
利用D3.js实现最简单的柱状图示例代码
2016/12/09 Javascript
jQuery弹出层插件popShow用法示例
2017/01/23 Javascript
详解vue组件化开发-vuex状态管理库
2017/04/10 Javascript
angularJs的ng-class切换class
2017/06/23 Javascript
Vue全家桶实践项目总结(推荐)
2017/11/04 Javascript
一种angular的方法级的缓存注解(装饰器)
2018/03/13 Javascript
jQuery+ajax实现用户登录验证
2020/09/13 jQuery
Python中还原JavaScript的escape函数编码后字符串的方法
2014/08/22 Python
python微信公众号开发简单流程
2018/03/23 Python
python实现字符串和字典的转换
2018/09/29 Python
Python流程控制 while循环实现解析
2019/09/02 Python
python pip安装包出现:Failed building wheel for xxx错误的解决
2019/12/25 Python
django xadmin action兼容自定义model权限教程
2020/03/30 Python
Django实现列表页商品数据返回教程
2020/04/03 Python
div或img图片高度随宽度自适应的方法
2020/02/06 HTML / CSS
日本高岛屋百货购物网站:TAKASHIMAYA
2019/03/24 全球购物
德国大型箱包和皮具商店:Koffer
2019/10/01 全球购物
JBL加拿大官方商店:扬声器、耳机等
2020/10/23 全球购物
介绍一下mysql的日期和时间函数
2013/03/28 面试题
高校生生产实习自我鉴定
2013/09/21 职场文书
参观监狱心得体会
2014/01/02 职场文书
社区七一党员活动方案
2014/01/25 职场文书
汽车销售经理岗位职责
2014/06/09 职场文书
2014年国庆晚会主持词
2014/09/19 职场文书
党员批评与自我批评(5篇)
2014/09/23 职场文书
四风对照检查材料范文
2014/09/27 职场文书
2014法制宣传日活动总结范文
2014/11/01 职场文书
检讨书模板
2015/01/29 职场文书
档案工作个人总结
2015/03/03 职场文书
2015年公司国庆放假通知
2015/07/30 职场文书
教师旷工检讨书
2015/08/15 职场文书
浅谈JavaScript作用域
2021/12/06 Javascript