解决 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实现页面蒙灰(mask)效果示例代码
Jun 20 Javascript
完美兼容IE,chrome,ff的设为首页、加入收藏及保存到桌面js代码
Dec 17 Javascript
javascript 兼容各个浏览器的事件
Feb 04 Javascript
JSONObject使用方法详解
Dec 17 Javascript
jQuery中的each()详细介绍(推荐)
May 25 Javascript
jquery实现多次上传同一张图片
Jan 09 Javascript
详解angular 中的自定义指令之详解API
Jun 20 Javascript
Vue-Router模式和钩子的用法
Feb 28 Javascript
axios发送post请求,提交图片类型表单数据方法
Mar 16 Javascript
node中的密码安全(加密)
Sep 17 Javascript
JavaScript常见鼠标事件与用法分析
Jan 03 Javascript
node.js文件操作系统实例详解
Nov 05 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迭代器实现斐波纳契数列的函数
2013/11/12 PHP
php数组冒泡排序算法实例
2016/05/06 PHP
Mootools 1.2教程 Fx.Tween的使用
2009/09/15 Javascript
js 无提示关闭浏览器页面的代码
2010/03/09 Javascript
JavaScript基础语法让人疑惑的地方小结
2012/05/23 Javascript
js获取当前月的第一天和最后一天的小例子
2013/11/18 Javascript
Jquery中offset()和position()的区别分析
2015/02/05 Javascript
jQuery事件绑定on()、bind()与delegate() 方法详解
2015/06/03 Javascript
js实现仿qq消息的弹出窗效果
2016/01/06 Javascript
JS生成一维码(条形码)功能示例
2017/01/19 Javascript
jQuery加密密码到cookie的实现代码
2017/04/18 jQuery
AngularJS 霸道的过滤器小结
2017/04/26 Javascript
详解几十行代码实现一个vue的状态管理
2019/01/28 Javascript
jQuery控制input只能输入数字和两位小数的方法
2019/05/16 jQuery
微信小程序点击保存图片到本机功能
2019/12/13 Javascript
原生js+canvas实现贪吃蛇效果
2020/08/02 Javascript
[45:40]Ti4 冒泡赛第二天NEWBEE vs NaVi 1
2014/07/15 DOTA
Python实现获取网站PR及百度权重
2015/01/21 Python
在Python的Tornado框架中实现简单的在线代理的教程
2015/05/02 Python
Python中str.format()详解
2017/03/12 Python
Python找出最小的K个数实例代码
2018/01/04 Python
实例分析python3实现并发访问水平切分表
2018/09/29 Python
Python中logging.NullHandler 的使用教程
2018/11/29 Python
基于python实现百度语音识别和图灵对话
2020/11/02 Python
北京振戎融通Java面试题
2015/09/03 面试题
音乐学院硕士生的自我评价分享
2013/11/01 职场文书
2014新年寄语
2014/01/20 职场文书
求职意向书范文
2014/04/01 职场文书
2014年毕业演讲稿范文
2014/05/13 职场文书
社区精神文明建设汇报材料
2014/08/17 职场文书
党支部组织生活会整改方案
2014/09/30 职场文书
抗洪救灾感谢信
2015/01/22 职场文书
2015年中职班主任工作总结
2015/05/25 职场文书
小马王观后感
2015/06/11 职场文书
2019企业文化管理制度范本!
2019/08/06 职场文书
Vue中使用import进行路由懒加载的原理分析
2022/04/01 Vue.js