解决 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 相关文章推荐
js的onload事件及初始化按钮事件示例代码
Sep 25 Javascript
node.js [superAgent] 请求使用示例
Mar 13 Javascript
jquery操作angularjs对象
Jun 26 Javascript
JS实现点击登录弹出窗口同时背景色渐变动画效果
Mar 25 Javascript
Vue2.0利用 v-model 实现组件props双向绑定的优美解决方案
Mar 13 Javascript
jQuery实现选中行变色效果(实例讲解)
Jul 06 jQuery
jQuery实现全选、反选和不选功能
Aug 16 jQuery
angular2组件中定时刷新并清除定时器的实例讲解
Aug 31 Javascript
浅谈Node框架接入ELK实践总结
Feb 22 Javascript
浅谈Javascript中的对象和继承
Apr 19 Javascript
JS前端基于canvas给图片添加水印
Nov 11 Javascript
React自定义hook的方法
Jun 25 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中http_build_query 的一个问题
2012/03/25 PHP
php获取远程文件大小
2015/10/20 PHP
PHP目录操作实例总结
2016/09/27 PHP
CI框架AR数据库操作常用函数总结
2016/11/21 PHP
highchart数据源纵轴json内的值必须是int(详解)
2017/02/20 PHP
yii2.0整合阿里云oss上传单个文件的示例
2017/09/19 PHP
网页的标准,IMG不支持onload标签怎么办
2006/06/29 Javascript
页面只有一个text的时候,回车自动submit的解决方法
2010/08/12 Javascript
Node.js开发指南中的简单实例(mysql版)
2013/09/17 Javascript
jQuery选择器源码解读(二):select方法
2015/03/31 Javascript
js事件监听器用法实例详解
2015/06/01 Javascript
jQuery实现放大镜效果实例代码
2016/03/17 Javascript
jQuery通过deferred对象管理ajax异步
2016/05/20 Javascript
js和C# 时间日期格式转换的简单实例
2016/05/28 Javascript
JavaScript数组方法大全(推荐)
2016/07/05 Javascript
JavaScript 数组- Array的方法总结(推荐)
2016/07/21 Javascript
Javascript 判断两个IP是否在同一网段实例代码
2016/11/28 Javascript
详解JavaScript事件循环机制
2018/09/07 Javascript
详解JavaScript中的函数、对象
2019/04/01 Javascript
Vue循环中多个input绑定指定v-model实例
2020/08/31 Javascript
[52:44]VGJ.T vs infamous Supermajor小组赛D组败者组第一轮 BO3 第一场 6.3
2018/06/04 DOTA
Linux下Python获取IP地址的代码
2014/11/30 Python
老生常谈Python之装饰器、迭代器和生成器
2017/07/26 Python
python2.7实现FTP文件下载功能
2018/04/15 Python
详解pandas安装若干异常及解决方案总结
2019/01/10 Python
python matplotlib实现双Y轴的实例
2019/02/12 Python
Pyqt5自适应布局实例
2019/12/13 Python
基于python使用tibco ems代码实例
2019/12/20 Python
Django中使用Json返回数据的实现方法
2020/06/03 Python
Python操作Elasticsearch处理timeout超时
2020/07/17 Python
中粮集团旗下食品网上购物网站:我买网
2016/09/22 全球购物
考试不及格的检讨书
2014/01/22 职场文书
致全体运动员广播稿
2014/02/01 职场文书
销售员岗位职责范本
2015/04/11 职场文书
position:sticky 粘性定位的几种巧妙应用详解
2021/04/24 HTML / CSS
Spring Cloud 中@FeignClient注解中的contextId属性详解
2021/09/25 Java/Android