解决 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继承--原型链继承和类式继承
Apr 08 Javascript
jQuery中关于ScrollableGridPlugin.js(固定表头)插件的使用逐步解析
Jul 17 Javascript
jquery中EasyUI使用技巧小结
Feb 10 Javascript
jQuery实现的AJAX简单弹出层效果代码
Nov 26 Javascript
js Canvas实现圆形时钟教程
Sep 19 Javascript
纯JS实现图片验证码功能并兼容IE6-8(推荐)
Apr 19 Javascript
微信小程序之蓝牙的链接
Sep 26 Javascript
vue-cli3.0 特性解读
Apr 22 Javascript
实用Javascript调试技巧分享(小结)
Jun 18 Javascript
VUE中使用HTTP库Axios方法详解
Feb 05 Javascript
解决removeEventListener 无法清除监听的问题
Oct 30 Javascript
Vue.js桌面端自定义滚动条组件之美化滚动条VScroll
Dec 01 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使用Smarty的相关注意事项及访问变量的几种方式
2011/12/08 PHP
php curl的深入解析
2013/06/02 PHP
基于PHP5魔术常量与魔术方法的详解
2013/06/13 PHP
Session 失效的原因汇总及解决丢失办法
2015/09/30 PHP
PHP内置加密函数详解
2016/11/20 PHP
张孝祥JavaScript学习阶段性总结(2)--(X)HTML学习
2007/02/03 Javascript
javascript实现的鼠标链接提示效果生成器代码
2007/06/28 Javascript
Jquery命名冲突解决的五种方案分享
2012/03/16 Javascript
jQuery动态添加 input type=file的实现代码
2012/06/14 Javascript
jquery submit ie6下失效的原因分析及解决方法
2013/11/15 Javascript
JQuery插件iScroll实现下拉刷新,滚动翻页特效
2014/06/22 Javascript
Javascript学习笔记之 对象篇(三) : hasOwnProperty
2014/06/24 Javascript
JavaScript常用小技巧小结
2014/12/29 Javascript
javascript折半查找详解
2015/01/26 Javascript
js钢琴按钮波浪式图片排列效果代码分享
2015/08/26 Javascript
jquery左右全屏大尺寸多图滑动效果代码分享
2015/08/28 Javascript
Jquery ajax请求导出Excel表格的实现代码
2016/06/08 Javascript
基于Bootstrap模态对话框只加载一次 remote 数据的解决方法
2017/07/09 Javascript
nodejs判断文件、文件夹是否存在及删除的方法
2017/11/10 NodeJs
使用weixin-java-tools完成微信授权登录、微信支付的示例
2018/09/26 Javascript
vue登录以及权限验证相关的实现
2019/10/25 Javascript
浅谈JavaScript窗体Window.ShowModalDialog使用
2020/07/22 Javascript
讲解python参数和作用域的使用
2013/11/01 Python
python学习--使用QQ邮箱发送邮件代码实例
2019/04/16 Python
Flask框架中request、请求钩子、上下文用法分析
2019/07/23 Python
使用python 计算百分位数实现数据分箱代码
2020/03/03 Python
学年自我鉴定范文
2013/10/01 职场文书
管理心得体会
2013/12/28 职场文书
小学数学教学经验交流材料
2014/05/22 职场文书
暑期学习心得体会
2014/09/02 职场文书
公司股东合作协议书
2014/09/14 职场文书
群众路线教育实践活动个人对照检查材料思想汇报(社区班子)
2014/10/06 职场文书
忠诚与背叛观后感
2015/06/04 职场文书
2015初中政治教学工作总结
2015/07/21 职场文书
如何用JS实现网页瀑布流布局
2021/04/24 Javascript
MySQL事务的隔离级别详情
2022/07/15 MySQL