解决 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实现标签页效果(配合css)
Apr 03 Javascript
js取两个数组的交集|差集|并集|补集|去重示例代码
Aug 07 Javascript
jQuery实现跨域
Feb 03 Javascript
Javascript BOM学习小结(六)
Nov 26 Javascript
Vue中的ref作用详解(实现DOM的联动操作)
Aug 21 Javascript
VUE2 前端实现 静态二级省市联动选择select的示例
Feb 09 Javascript
webpack 插件html-webpack-plugin的具体使用
Apr 09 Javascript
Vue 报错TypeError: this.$set is not a function 的解决方法
Dec 17 Javascript
vue实现压缩图片预览并上传功能(promise封装)
Jan 10 Javascript
js实现一个简易计算器
Mar 30 Javascript
jQuery加PHP实现图片上传并提交的示例代码
Jul 16 jQuery
解决nuxt页面中mounted、created、watch执行两遍的问题
Nov 05 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无限分类代码,支持数组格式化、直接输出菜单两种方式
2011/05/18 PHP
php 数组字符串搜索array_search技巧
2016/07/05 PHP
jquery+thinkphp实现跨域抓取数据的方法
2016/10/15 PHP
动态样式类封装JS代码
2009/09/02 Javascript
关于JavaScript中var声明变量作用域的推断
2010/12/16 Javascript
jQuery对表单的操作代码集合
2011/04/06 Javascript
javascript垃圾收集机制与内存泄漏详细解析
2013/11/11 Javascript
JavaScript插件化开发教程(五)
2015/02/01 Javascript
JS实现淘宝支付宝网站的控制台菜单效果
2015/09/28 Javascript
bootstrap datepicker限定可选时间范围实现方法
2016/09/28 Javascript
微信小程序 五星评分(包括半颗星评分)实例代码
2016/12/14 Javascript
js中json对象和字符串的理解及相互转化操作实现方法
2017/09/22 Javascript
Bootstrap实现可折叠分组侧边导航菜单
2018/03/07 Javascript
vue点击当前路由高亮小案例
2019/09/26 Javascript
Vue.js标签页组件使用方法详解
2019/10/19 Javascript
一起写一个即插即用的Vue Loading插件实现
2019/10/31 Javascript
jquery实现点击弹出对话框
2020/02/08 jQuery
解决vue+elementui项目打包后样式变化问题
2020/08/03 Javascript
vue 防止页面加载时看到花括号的解决操作
2020/11/09 Javascript
[01:13:59]LGD vs Mineski Supermajor 胜者组 BO3 第三场 6.5
2018/06/06 DOTA
[52:36]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第一场 8.19
2018/08/21 DOTA
python 采集中文乱码问题的完美解决方法
2016/09/27 Python
详解利用django中间件django.middleware.csrf.CsrfViewMiddleware防止csrf攻击
2018/10/09 Python
详解python中@的用法
2019/03/27 Python
详解python编译器和解释器的区别
2019/06/24 Python
python中时间转换datetime和pd.to_datetime详析
2019/08/11 Python
Python3视频转字符动画的实例代码
2019/08/29 Python
深入了解Python在HDA中的应用
2019/09/05 Python
详解pyinstaller生成exe的闪退问题解决方案
2020/06/19 Python
Python grequests模块使用场景及代码实例
2020/08/10 Python
Python实现AES加密,解密的两种方法
2020/10/03 Python
CSS3实现div从下往上滑入滑出效果示例
2020/04/28 HTML / CSS
美国波西米亚风格精品店:South Moon Under
2019/10/26 全球购物
两道JAVA笔试题
2016/09/14 面试题
城市轨道交通工程职业规划书范文
2014/01/18 职场文书
材料工程专业毕业生求职信
2014/03/04 职场文书