解决 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 相关文章推荐
超清晰的document对象详解
Feb 27 Javascript
Javascript实现返回上一页面并刷新的小例子
Dec 11 Javascript
使用jquery操作session方法分享
Jan 22 Javascript
jQuery中next方法用法实例
Apr 24 Javascript
JavaScript如何实现图片懒加载(lazyload) 提高用户体验(增强版)
Nov 30 Javascript
如何解决hover在ie6中的兼容性问题
Dec 15 Javascript
Vue 2.5.2下axios + express 本地请求404的解决方法
Feb 21 Javascript
在Node.js下运用MQTT协议实现即时通讯及离线推送的方法
Jan 24 Javascript
微信小程序云开发之新手环境配置
May 16 Javascript
vue项目中将element-ui table表格写成组件的实现代码
Jun 12 Javascript
js实现tab栏切换效果
Aug 02 Javascript
Vue如何跨组件传递Slot的实现
Dec 14 Vue.js
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 print EOF实现方法
2009/05/21 PHP
PHP读取文件的常见几种方法
2016/11/03 PHP
php单元测试phpunit入门实例教程
2017/11/17 PHP
js实现通用的微信分享组件示例
2014/03/10 Javascript
jQuery打印图片pdf、txt示例代码
2014/07/22 Javascript
javascript自动生成包含数字与字符的随机字符串
2015/02/09 Javascript
JavaScript中判断函数、变量是否存在
2015/06/10 Javascript
jquery实现带缩略图的可定制高度画廊效果(5种)
2015/08/28 Javascript
使用JavaScript和CSS实现文本隔行换色的方法
2015/11/04 Javascript
jQuery实现联动下拉列表查询框
2017/01/04 Javascript
javaScript嗅探执行神器-sniffer.js
2017/02/14 Javascript
Vue 兄弟组件通信的方法(不使用Vuex)
2017/10/26 Javascript
JS删除数组里的某个元素方法
2018/02/03 Javascript
JS获取表格视图所选行号的ids过程解析
2020/02/21 Javascript
手机浏览器唤起微信分享(JS)
2020/10/11 Javascript
[01:08:24]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第一场 2月5日
2021/03/11 DOTA
python爬取网站数据保存使用的方法
2013/11/20 Python
python格式化字符串实例总结
2014/09/28 Python
在IIS服务器上以CGI方式运行Python脚本的教程
2015/04/25 Python
将Emacs打造成强大的Python代码编辑工具
2015/11/20 Python
解决python 无法加载downsample模型的问题
2018/10/25 Python
Django 路由控制的实现
2019/07/17 Python
pytorch 共享参数的示例
2019/08/17 Python
python连接mysql数据库并读取数据的实现
2020/09/25 Python
HTML5 localStorage使用总结
2017/02/22 HTML / CSS
html5给汉字加拼音加进度条的实现代码
2020/04/07 HTML / CSS
Hotels.com南非:酒店预订
2017/11/02 全球购物
经典c++面试题五
2014/12/17 面试题
使用Vue.js和MJML创建响应式电子邮件
2021/03/23 Vue.js
企业总经理任命书
2014/06/05 职场文书
人力资源管理专业求职信
2014/07/23 职场文书
社区关爱留守儿童活动方案
2014/08/22 职场文书
2014年个人技术工作总结
2014/12/08 职场文书
幼儿园万圣节活动总结
2015/05/05 职场文书
详解JavaScript中的执行上下文及调用堆栈
2021/04/29 Javascript