解决 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 相关文章推荐
jquery ui dialog ie8出现滚动条的解决方法
Dec 06 Javascript
基于jquery封装的一个js分页
Nov 15 Javascript
分享9个最好用的JavaScript开发工具和代码编辑器
Mar 24 Javascript
JS实现为排序好的字符串找出重复行的方法
Mar 02 Javascript
超链接怎么正确调用javascript函数
May 23 Javascript
jQuery插件HighCharts绘制的2D堆柱状图效果示例【附demo源码下载】
Mar 14 Javascript
Node.JS 循环递归复制文件夹目录及其子文件夹下的所有文件
Sep 18 Javascript
详解在vue-cli项目中使用mockjs(请求数据删除数据)
Oct 23 Javascript
Angular2的管道Pipe的使用方法
Nov 07 Javascript
JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解
Aug 16 Javascript
vue数据更新UI不刷新显示的解决办法
Aug 06 Javascript
vue中实现点击变成全屏的多种方法
Sep 27 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 radio 单选框获取与保持值的实现代码
2010/05/15 PHP
PHP SEO优化之URL优化方法
2011/04/21 PHP
php 购物车完整实现代码
2014/06/05 PHP
php列出mysql表所有行和列的方法
2015/03/13 PHP
PHP+JS实现的商品秒杀倒计时用法示例
2016/11/15 PHP
thinkPHP5.0框架安装教程
2017/03/25 PHP
javascript-表格排序(降序/反序)实现介绍(附图)
2013/05/30 Javascript
一个网页标题title的闪动提示效果实现思路
2014/03/22 Javascript
jQuery中append()方法用法实例
2014/12/25 Javascript
JS使用ajax从xml文件动态获取数据显示的方法
2015/03/24 Javascript
关于Javascript回调函数的一个妙用
2016/08/29 Javascript
AngularJs Dependency Injection(DI,依赖注入)
2016/09/02 Javascript
总结几道关于Node.js的面试问题
2017/01/11 Javascript
微信小程序 点击控件后选中其它反选实例详解
2017/02/21 Javascript
全站最详细的Vuex教程
2018/04/13 Javascript
微信小程序js文件改变参数并在视图上及时更新【推荐】
2018/06/11 Javascript
vue项目base64字符串转图片的实现代码
2018/07/13 Javascript
javascript json字符串到json对象转义问题
2019/01/22 Javascript
vue实现select下拉显示隐藏功能
2019/09/30 Javascript
Vue组件简易模拟实现购物车
2020/12/21 Vue.js
python zip文件 压缩
2008/12/24 Python
python解析基于xml格式的日志文件
2017/02/25 Python
使用sklearn之LabelEncoder将Label标准化的方法
2018/07/11 Python
H5页面适配iPhoneX(就是那么简单)
2019/12/02 HTML / CSS
美国电视购物:QVC
2017/02/06 全球购物
Shopee越南:东南亚与台湾电商平台
2019/02/03 全球购物
FORZIERI福喜利中国官网:奢侈品购物梦工厂
2019/05/03 全球购物
乌克兰电子和家用电器商店:Foxtrot
2019/07/23 全球购物
什么是Linux虚拟文件系统VFS
2012/01/31 面试题
销售顾问的岗位职责
2013/11/13 职场文书
工程管理专业个人求职信范文
2013/12/07 职场文书
项目管理计划书
2014/01/09 职场文书
《落花生》教学反思
2014/02/25 职场文书
3分钟英语演讲稿
2014/04/29 职场文书
人力资源管理专业毕业生自荐书
2014/05/25 职场文书
党员评议表自我评价范文
2014/10/20 职场文书