解决 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改变文章字体大小的实例代码
Nov 27 Javascript
jquery live()调用不存在的解决方法
Feb 26 Javascript
jQuery UI插件自定义confirm确认框的方法
Mar 20 Javascript
javascript省市区三级联动下拉框菜单实例演示
Nov 29 Javascript
在js里怎么实现Xcode里的callFuncN方法(详解)
Nov 05 Javascript
jQuery源码分析之sizzle选择器详解
Feb 13 Javascript
JS中mouseup事件丢失的原因与解决办法
Jun 14 Javascript
轻松玩转BootstrapTable(后端使用SpringMVC+Hibernate)
Sep 06 Javascript
node.js 用socket实现聊天的示例代码
Oct 17 Javascript
浅谈js的解析顺序 作用域 严格模式
Oct 23 Javascript
JavaScript基础心法 数据类型
Mar 05 Javascript
jquery操作select常见方法大全【7种情况】
May 28 jQuery
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.ini实现Mysql导入数据库文件最大限制的修改方法
2007/12/11 PHP
PHP中的float类型使用说明
2010/07/27 PHP
php获取后台Job管理的实现代码
2011/06/10 PHP
PHP封装CURL扩展类实例
2015/07/28 PHP
PHP使用mkdir创建多级目录的方法
2015/12/22 PHP
CSS中简写属性要注意TRouBLe的顺序问题(避免踩坑)
2021/03/09 HTML / CSS
浅谈JavaScript中面向对象技术的模拟
2006/09/25 Javascript
javascript和HTML5利用canvas构建猜牌游戏实现算法
2013/07/17 Javascript
JS 新增Cookie 取cookie值 删除cookie 举例详解
2014/10/10 Javascript
js字符串完全替换函数分享
2014/12/03 Javascript
jquery实现标签上移、下移、置顶
2015/04/26 Javascript
js中this用法实例详解
2015/05/05 Javascript
JS控制表单提交的方法
2015/07/09 Javascript
基于AngularJS+HTML+Groovy实现登录功能
2016/02/17 Javascript
bootstrap多种样式进度条展示
2016/12/20 Javascript
select下拉框插件jquery.editable-select详解
2017/01/22 Javascript
Vue2.0 v-for filter列表过滤功能的实现
2018/09/07 Javascript
微信小程序 子级页面返回父级并把子级参数带回父级实现方法
2019/08/22 Javascript
用Golang运行JavaScript的实现示例
2019/11/25 Javascript
js实现小球在页面规定的区域运动
2020/06/16 Javascript
写一个Vue loading 插件
2020/11/09 Javascript
nodejs中的异步编程知识点详解
2021/01/17 NodeJs
在主机商的共享服务器上部署Django站点的方法
2015/07/22 Python
Python的Flask框架中SQLAlchemy使用时的乱码问题解决
2015/11/07 Python
python一键去抖音视频水印工具
2018/09/14 Python
对Django的restful用法详解(自带的增删改查)
2019/08/28 Python
Pycharm debug调试时带参数过程解析
2020/02/03 Python
python plt可视化——打印特殊符号和制作图例代码
2020/04/17 Python
Matplotlib自定义坐标轴刻度的实现示例
2020/06/18 Python
安装python依赖包psycopg2来调用postgresql的操作
2021/01/01 Python
德国最大的网上鞋店之一:Schuhe24.de
2017/06/10 全球购物
摩飞电器俄罗斯官方网站:Morphy Richards俄罗斯
2020/07/30 全球购物
毕业生自我鉴定
2013/11/05 职场文书
詹天佑教学反思
2014/04/30 职场文书
力克胡哲观后感
2015/06/10 职场文书
MySQL数据库10秒内插入百万条数据的实现
2021/11/01 MySQL