解决 window.onload 被覆盖的问题方法

手头在维护一个比较老的项目,由于页面的重组,一些不同页面的 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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • js window.onload 加载多个函数的方法

    用法如下: function func(){alert("this is window onload event!");return;} window.onload=func; 或者如下: window.onload=function(){alert("this is window onload event!");return;} 但window.onload 不能同时加载多个函数. 比如: 复制代码 代码如下: function t(){ alert("

  • window.onload使用指南

    网页中的javascript脚本代码往往需要在文档加载完成后才能够去执行,否则可能导致无法获取对象的情况,为了避免这种情况的发生,可以使用以下两种方式: 一.将脚本代码放在网页的低端,这样在运行脚本代码的时候,可以确保要操作的对象已经加载完成. 二.通过window.onload来执行脚本代码. 第一种方式感觉比较凌乱(其实推荐使用),往往我们需要将脚本代码放在一个更为合适的地方,那么window.onload方式就是一个更好的选择.window.onload是一个事件,当文档加载完成之后就会触

  • 浅析document.ready和window.onload的区别讲解

    Javascript 只有在DOM元素已经定义以后才可以对其执行某种操作,这个问题在"javascript执行顺序里"http://www.jb51.net/article/44577.htm一文里有详细介绍. jQuery使用document.ready来保证所要执行的代码是在DOM元素被加载完成的情况下执行.比如在"jQuery基础 - 如何开始"一文里,我用到如下jQuery代码: 复制代码 代码如下: <!--   $(document).ready(

  • 在chrome中window.onload事件的一些问题

    假如我们有一个如下的页面: 复制代码 代码如下: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title></title> <meta http-equiv="Content-Type" content="

  • JS:window.onload的使用介绍

    1.最简单的调用方式 直接写到html的body标签里面,如: 复制代码 代码如下: <html> <body onload="func()"> </body> </html> 2.在JS语句调用 复制代码 代码如下: <script type="text/javascript"> function func(){--} window.onload=func; </script> 3.同时 调用

  • window.onload和$(function(){})的区别介绍

    复制代码 代码如下: window.onload=function{} 表示页面加载完了后(包括dom和js),再执行函数里面的内容: 复制代码 代码如下: $(function(){}) 表示页面(dom)加载完了后,再执行函数里面的内容

  • window.onload绑定多个事件的两种解决方案

    前言 有些函数,必须在网页加载完毕后执行.比如:涉及DOM操作的. 网页加载完毕时会触发一个onload事件,将函数绑定到这个事件上即可. 复制代码 代码如下: window.onload = myFunction; 问题来了:如果需要同时绑定多个事件,该如何处理呢?有两种解决方法 方案一 创建一个匿名函数,来容纳需要绑定的多个事件,再讲这个匿名函数绑定到onload事件上 window.onload = function(){ firstFunction(); secondFunction()

  • 判断window.onload是否多次使用的方法

    window.onload想必大家都有使用过吧,在窗口加载时执行,如果多次使用window.onload该如何判断呢?看看下面的代码 <script> function onloadCallback(){ //Todo } if (window.onload) { var onload_random = 'onload'+Math.random(); window[onload_random] = window.onload; window.onload = function (){ wind

  • js window.onload 加载多个函数和追加函数详解

    平时做项目 经常需要使用window.onload, 用法如下: function func(){alert("this is window onload event!");return;} window.onload=func; 或者如下: window.onload=function(){alert("this is window onload event!");return;} 但window.onload 不能同时加载多个函数. 比如: function t

  • window.onload追加函数使用示例

    复制代码 代码如下: <script type="text/javascript"> function tt1(){ alert('tt1') ; } function tt2(){ alert('tt2') ; } function tt3(){ alert('tt3') ; } function addLoadEvent(func) { var oldonload = window.onload; if (typeof window.onload != 'functio

  • jquery中的$(document).ready()与window.onload的区别

    所以如果某个图片或者其他资源加载很长时间, 访问者就会看到一个不完整的页面, 甚至在图片加载之前就执行了需要依赖动态添加的元素的脚本而导致脚本错误.window.onload = function() { testDiv.innerHTML = "<div style=\"border:solid 1px #FF0000\">动态创建的div</div>"; } 解决办法就是等DOM被解析后, 在图像和外部资源加载之前执行我们的函数.在jQu

随机推荐