解决 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 相关文章推荐
JavaScript 开发规范要求(图文并茂)
Jun 11 Javascript
jquery插件NProgress.js制作网页加载进度条
Jun 05 Javascript
javascript中JSON对象与JSON字符串相互转换实例
Jul 11 Javascript
jQuery实现的网页竖向菜单效果代码
Aug 26 Javascript
理解javascript中try...catch...finally
Dec 25 Javascript
JS+Canvas 实现下雨下雪效果
May 18 Javascript
全面解析Bootstrap中transition、affix的使用方法
May 30 Javascript
JS使用cookie设置样式的方法
Jun 30 Javascript
Bootstrap3 模态框使用实例
Feb 22 Javascript
JS解惑之Object中的key是有序的么
May 06 Javascript
通过js实现压缩图片上传功能
Feb 25 Javascript
js 使用ajax设置和获取自定义header信息的方法小结
Mar 12 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
全国FM电台频率大全 - 6 辽宁省
2020/03/11 无线电
一次编写,随处运行
2006/10/09 PHP
PHP4在WinXP下IIS和Apache2服务器上的安装实例
2006/10/09 PHP
ThinkPHP的RBAC(基于角色权限控制)深入解析
2013/06/17 PHP
CodeIgniter框架数据库事务处理的设计缺陷和解决方案
2014/07/25 PHP
php中字符集转换iconv函数使用总结
2014/10/11 PHP
thinkPHP简单遍历数组方法分析
2016/05/16 PHP
javascript 日期时间函数(经典+完善+实用)
2009/05/27 Javascript
jQuery 幻灯片插件(带缩略图功能)
2011/01/24 Javascript
jquery实现div阴影效果示例代码
2013/09/16 Javascript
JavaScript数组常用操作技巧汇总
2014/11/17 Javascript
深入理解JavaScript系列(28):设计模式之工厂模式详解
2015/03/03 Javascript
JavaScript编程中window的location与history对象详解
2015/10/26 Javascript
jstl中判断list中是否包含某个值的简单方法
2016/10/14 Javascript
浅析JavaScript中break、continue和return的区别
2016/11/30 Javascript
bootstrap弹出层的多种触发方式
2017/05/10 Javascript
详解vue中使用express+fetch获取本地json文件
2017/10/10 Javascript
解决element ui select下拉框不回显数据问题的解决
2019/02/20 Javascript
详解ES6 export default 和 import语句中的解构赋值
2019/05/28 Javascript
python中getattr函数使用方法 getattr实现工厂模式
2014/01/20 Python
Python实现把utf-8格式的文件转换成gbk格式的文件
2015/01/22 Python
Python2.7简单连接与操作MySQL的方法
2016/04/27 Python
解决Pycharm中import时无法识别自己写的程序方法
2018/05/18 Python
Python2和Python3.6环境解决共存问题
2018/11/09 Python
国家地理在线商店:Shop National Geographic
2018/06/30 全球购物
Manuka Doctor英国官网:真正的麦卢卡蜂蜜和护肤品
2018/10/26 全球购物
Vinatis德国:法国领先的葡萄酒邮购公司
2020/09/07 全球购物
C++:memset ,memcpy和strcpy的根本区别
2013/04/27 面试题
国外的一些J2EE面试题一
2012/10/13 面试题
大学生求职简历的自我评价范文
2013/10/12 职场文书
体育教师个人的自我评价
2014/02/16 职场文书
《愚公移山》教学反思
2014/02/20 职场文书
《雪儿》教学反思
2014/04/17 职场文书
导游词之蓬莱长岛
2019/12/17 职场文书
浅谈golang 中time.After释放的问题
2021/05/05 Golang
MySQL 外连接语法之 OUTER JOIN
2022/04/09 MySQL