解决 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 相关文章推荐
屏蔽网页右键复制和ctrl+c复制的js代码
Jan 04 Javascript
javascript和HTML5利用canvas构建猜牌游戏实现算法
Jul 17 Javascript
JavaScript字符串对象replace方法实例(用于字符串替换或正则替换)
Oct 16 Javascript
jQuery调取jSon数据并展示的方法
Jan 29 Javascript
浅谈javascript获取元素transform参数
Jul 24 Javascript
Knockout自定义绑定创建方法
Dec 26 Javascript
微信开发 使用picker封装省市区三级联动模板
Oct 28 Javascript
JavaScript 异步调用
Oct 25 Javascript
Vue插件打包与发布的方法示例
Aug 20 Javascript
vue+element实现表单校验功能
May 20 Javascript
JS实现纵向轮播图(初级版)
Jan 18 Javascript
JS如何寻找数组中心索引过程解析
Jun 01 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
与空气斗智斗勇的经典《Overlord》,传说中的“无稽之谈”
2020/04/09 日漫
PHP基础教程(php入门基础教程)一些code代码
2013/01/06 PHP
zf框架的校验器使用使用示例(自定义校验器和校验器链)
2014/03/13 PHP
PHP中Fatal error session_start()错误解决步骤
2014/08/05 PHP
PHP进制转换实例分析(2,8,16,36,64进制至10进制相互转换)
2017/02/04 PHP
jQuery与ExtJS之选择实例分析
2010/08/19 Javascript
JS动态修改图片的URL(src)的方法
2015/04/01 Javascript
ES6中如何使用Set和WeakSet
2016/03/10 Javascript
Angularjs 自定义服务的三种方式(推荐)
2016/08/02 Javascript
对称加密与非对称加密优缺点详解
2017/02/06 Javascript
nodejs个人博客开发第六步 数据分页
2017/04/12 NodeJs
bootstrap实现点击删除按钮弹出确认框的实例代码
2018/08/16 Javascript
了解JavaScript表单操作和表单域
2019/05/27 Javascript
js/jQuery实现全选效果
2019/06/17 jQuery
聊聊鉴权那些事(推荐)
2019/08/22 Javascript
微信小程序实现签到弹窗动画
2020/09/21 Javascript
[16:14]教你分分钟做大人:米拉娜(HEROS)
2014/11/24 DOTA
[03:11]不朽宝藏三外观展示
2020/09/18 DOTA
Python版的文曲星猜数字游戏代码
2013/09/02 Python
python基于http下载视频或音频
2018/06/20 Python
基于Python实现扑克牌面试题
2019/12/11 Python
Python标准库shutil模块使用方法解析
2020/03/10 Python
带你学习Python如何实现回归树模型
2020/07/16 Python
python线程里哪种模块比较适合
2020/08/02 Python
Python开发入门——迭代的基本使用
2020/09/03 Python
python 基于opencv实现高斯平滑
2020/12/18 Python
CSS3实现曲线阴影和翘边阴影
2016/05/03 HTML / CSS
Tripadvisor新西兰:阅读评论,比较价格和酒店预订
2018/02/10 全球购物
PHP开发工程师面试问题集锦
2012/11/01 面试题
天逸系统(武汉)有限公司Java笔试题
2015/12/29 面试题
演讲稿开场白
2014/01/13 职场文书
公司投资建议书
2014/05/16 职场文书
公民代理授权委托书
2014/09/24 职场文书
科技活动周标语
2014/10/08 职场文书
离婚协议书的范本
2015/01/27 职场文书
初一年级组工作总结
2015/08/12 职场文书