无法同时加载clock.js与sparkles.js两个脚本的问题求助
问题根源与修复方案
核心冲突点
你的两个脚本存在两处致命问题,导致无法同时运行:
window.onload被覆盖:两个脚本都直接给window.onload赋值,后加载的脚本会完全替换前一个的初始化逻辑,最终只有最后一个脚本的代码执行。- 全局变量/函数冲突:两个脚本都定义了全局变量
colour和全局函数createDiv,后加载的脚本会覆盖前一个的同名内容,导致其中一个脚本的逻辑因依赖被破坏而失效。
修复步骤
1. 替换window.onload赋值为事件监听
不要直接给window.onload赋值,改用addEventListener绑定多个初始化函数,这样两个脚本的启动逻辑都会被执行:
// clock.js 替换原window.onload代码 window.addEventListener('load', function() { if (document.getElementById) { // 原clock初始化代码保留 clok=document.createElement("div"); clok.style.position="absolute"; // ...省略其余初始化代码 tick(); } }); // sparkles.js 替换原window.onload代码 window.addEventListener('load', function() { if (document.getElementById) { // 原sparkles初始化代码保留 var i, rats, rlef, rdow; for (var i=0; i<sparkles; i++) { // ...省略其余初始化代码 } set_width(); sparkle(); } });
2. 隔离全局变量与函数
把每个脚本的代码封装到**立即执行函数表达式(IIFE)**中,避免全局污染,同时重命名冲突的函数/变量:
修改后的clock.js
(function() { var clockColour = "#000000"; // 重命名colour避免冲突 var clock_size=8; var clok; var cpos=0; var newx=xmo=100; var newy=ymo=30; window.addEventListener('load', function() { if (document.getElementById) { clok=document.createElement("div"); clok.style.position="absolute"; clok.appendChild(createDigit("dig0")); clok.appendChild(createDigit("dig1")); clok.appendChild(createColon()); clok.appendChild(createDigit("dig2")); clok.appendChild(createDigit("dig3")); clok.appendChild(createColon("ms")); clok.appendChild(createDigit("dig4")); clok.appendChild(createDigit("dig5")); document.body.appendChild(clok); tick(); } }); var digit=new Array(247, 146, 221, 219, 186, 235, 239, 210, 255, 251); function tick() { var now=new Date(); var t=Math.floor(now.getTime()/500)%2; var i, j, k; var won=oo(now.getHours())+oo(now.getMinutes())+oo(now.getSeconds()); for (i=0; i<6; i++) for (j=0; j<7; j++) { k=digit[won.substring(i, i+1)].toString(2).substring(j+1, j+2); document.getElementById("dig"+i+j).style.backgroundColor=(k==1)?clockColour:"transparent"; } document.getElementById("mstop").style.backgroundColor=(t)?"transparent":clockColour; document.getElementById("msbot").style.backgroundColor=(t)?"transparent":clockColour; xmo+=Math.floor((newx-xmo)/4); clok.style.left=Math.round(xmo-(clock_size+2)*4)+"px"; ymo+=Math.floor((newy-ymo)/4); clok.style.top=Math.round(ymo-clock_size*2.5)+"px"; setTimeout(tick, 40); // 改用函数引用替代字符串调用 } function scro() { var scro=0; if (document.body.scrollTop) scro=document.body.scrollTop; else if (document.documentElement && document.documentElement.scrollTop) scro=document.documentElement.scrollTop; return (scro); } function oo(o) { return(((o<10)?"0"+o:o).toString()); } function createDigit(id) { var odiv=createClockDiv(0, cpos, clock_size+clock_size+2, clock_size+2, false); cpos+=clock_size+4; odiv.appendChild(createClockDiv(0, 1, 2, clock_size, id+"0")); odiv.appendChild(createClockDiv(1, 0, clock_size, 2, id+"1")); odiv.appendChild(createClockDiv(1, clock_size, clock_size, 2, id+"2")); odiv.appendChild(createClockDiv(clock_size, 1, 2, clock_size, id+"3")); odiv.appendChild(createClockDiv(clock_size+1, 0, clock_size, 2, id+"4")); odiv.appendChild(createClockDiv(clock_size+1, clock_size, clock_size, 2, id+"5")); odiv.appendChild(createClockDiv(clock_size+clock_size, 1, 2, clock_size, id+"6")); return (odiv); } function createColon(id) { var odiv=createClockDiv(0, cpos, clock_size+clock_size+2, 2, false); cpos+=4; var dot1=createClockDiv(4, 0, 3, 2, (id)?id+"top":false); dot1.style.backgroundColor=clockColour; odiv.appendChild(dot1); var dot2=createClockDiv(clock_size+clock_size-5, 0, 3, 2, (id)?id+"bot":false); dot2.style.backgroundColor=clockColour; odiv.appendChild(dot2); return (odiv); } // 重命名createDiv为createClockDiv function createClockDiv(top, left, height, width, id) { var div=document.createElement("div"); div.style.position="absolute"; div.style.top=top+"px"; div.style.left=left+"px"; div.style.height=height+"px"; div.style.width=width+"px"; div.style.overflow="hidden"; if (id) div.setAttribute("id", id); return (div); } })();
修改后的sparkles.js
(function() { var sparkleColour = "#FFFFFF"; // 重命名colour避免冲突 var sparkles=120; var x=ox=400; var y=oy=300; var swide=800; var shigh=600; var sleft=sdown=0; var tiny=new Array(); var star=new Array(); var starv=new Array(); var starx=new Array(); var stary=new Array(); var tinyx=new Array(); var tinyy=new Array(); var tinyv=new Array(); window.addEventListener('load', function() { if (document.getElementById) { var i, rats, rlef, rdow; for (var i=0; i<sparkles; i++) { var rats=createSparkleDiv(3, 3); rats.style.visibility="hidden"; document.body.appendChild(tiny[i]=rats); starv[i]=0; tinyv[i]=0; var rats=createSparkleDiv(5, 5); rats.style.backgroundColor="transparent"; rats.style.visibility="hidden"; var rlef=createSparkleDiv(1, 5); var rdow=createSparkleDiv(5, 1); rats.appendChild(rlef); rats.appendChild(rdow); rlef.style.top="2px"; rlef.style.left="0px"; rdow.style.top="0px"; rdow.style.left="2px"; document.body.appendChild(star[i]=rats); } set_width(); sparkle(); } }); function sparkle() { var c; if (x!=ox || y!=oy) { ox=x; oy=y; for (c=0; c<sparkles; c++) if (!starv[c]) { star[c].style.left=(starx[c]=x)+"px"; star[c].style.top=(stary[c]=y)+"px"; star[c].style.clip="rect(0px, 5px, 5px, 0px)"; star[c].style.visibility="visible"; starv[c]=50; break; } } for (c=0; c<sparkles; c++) { if (starv[c]) update_star(c); if (tinyv[c]) update_tiny(c); } setTimeout(sparkle, 40); // 改用函数引用替代字符串调用 } function update_star(i) { if (--starv[i]==25) star[i].style.clip="rect(1px, 4px, 4px, 1px)"; if (starv[i]) { stary[i]+=1+Math.random()*3; if (stary[i]<shigh+sdown) { star[i].style.top=stary[i]+"px"; starx[i]+=(i%5-2)/5; star[i].style.left=starx[i]+"px"; } else { star[i].style.visibility="hidden"; starv[i]=0; return; } } else { tinyv[i]=50; tiny[i].style.top=(tinyy[i]=stary[i])+"px"; tiny[i].style.left=(tinyx[i]=starx[i])+"px"; tiny[i].style.width="2px"; tiny[i].style.height="2px"; star[i].style.visibility="hidden"; tiny[i].style.visibility="visible" } } function update_tiny(i) { if (--tinyv[i]==25) { tiny[i].style.width="1px"; tiny[i].style.height="1px"; } if (tinyv[i]) { tinyy[i]+=1+Math.random()*3; if (tinyy[i]<shigh+sdown) { tiny[i].style.top=tinyy[i]+"px"; tinyx[i]+=(i%5-2)/5; tiny[i].style.left=tinyx[i]+"px"; } else { tiny[i].style.visibility="hidden"; tinyv[i]=0; return; } } else tiny[i].style.visibility="hidden"; } document.onmousemove=mouse; function mouse(e) { set_scroll(); y=(e)?e.pageY:event.y+sdown; x=(e)?e.pageX:event.x+sleft; } function set_scroll() { if (typeof(self.pageYOffset)=="number") { sdown=self.pageYOffset; sleft=self.pageXOffset; } else if (document.body.scrollTop || document.body.scrollLeft) { sdown=document.body.scrollTop; sleft=document.body.scrollLeft; } else if (document.documentElement && (document.documentElement.scrollTop || document.documentElement.scrollLeft)) { sleft=document.documentElement.scrollLeft; sdown=document.documentElement.scrollTop; } else { sdown=0; sleft=0; } } window.onresize=set_width; function set_width() { if (typeof(self.innerWidth)=="number") { swide=self.innerWidth; shigh=self.innerHeight; } else if (document.documentElement && document.documentElement.clientWidth) { swide=document.documentElement.clientWidth; shigh=document.documentElement.clientHeight; } else if (document.body.clientWidth) { swide=document.body.clientWidth; shigh=document.body.clientHeight; } } // 重命名createDiv为createSparkleDiv function createSparkleDiv(height, width) { var div=document.createElement("div"); div.style.position="absolute"; div.style.height=height+"px"; div.style.width=width+"px"; div.style.overflow="hidden"; div.style.backgroundColor=sparkleColour; return (div); } })();
3. 保留原引入方式
修改后的脚本可以继续使用原来的HTML引入逻辑,无需调整顺序:
<!DOCTYPE html> <html> <head> <script src="/clock.js"></script> <link rel="shortcut icon" href="icon.ico"> <link rel="apple-touch-icon" href="icon.ico"/> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Title</title> <script src="/sparkles.js"></script> </head> <body></body> </html>
额外优化建议
- 把
setTimeout("函数名()", 时间)的写法改成setTimeout(函数名, 时间),避免字符串解析带来的性能损耗和潜在安全问题,上面的代码已经完成了这个修改。 - 若追求性能,可以将两个脚本合并为一个文件,减少HTTP请求次数。
内容的提问来源于stack exchange,提问作者Das
相关产品推荐
相关产品推荐

