Javascript 函数调用在 head 中失败,但在 body 中没有
Javascript function call fails in head, but not in body
解决方案:我将排队机制调用到 window.onload 的方式似乎有问题。
序言 - 我很高兴看到我被标记为重复,解决方案是使用 window.onload,这是我已经在这里使用的东西。一些评论指出了我从另一个 Whosebug 解决方案中获得的 queue 可能存在的问题,但由于缺乏详细说明而让我一无所知。
问题:如果我在head中进行函数调用,它会失败。如果我在 body 中进行函数调用,它会成功。为什么?
扩展:为什么调用失败调用上方的 global.js 中的同一函数会成功?
我有一些 javascript 创建了一个 onload "queue" 类型(global.js 中的函数 addLoadEvent)。当调用 onload 时,调用此函数会添加到 queue。
除此之外,我发现如果某个脚本函数位于头部而不是 body,则它会失败。我不明白为什么,因为所需的一切(其他 js 函数)都在函数调用本身之上加载,并且直到 onload 才触发对该函数的实际调用,确保存在必要的 html 元素.
加载顺序:
- html 文件到头
- global.js - 包括 addLoadEvent(func)
- addLoadEvent x2(成功)
- head 中的内联脚本 - 包括 initialFighter()
- addLoadEvent(位置一 - 失败)
- html 头部后的文件
- addLoadEvent(位置二 - 成功)
- onload 触发 queued 次调用
为了这个问题的目的,根据它的位置失败或成功的函数调用如下。
addLoadEvent(initialFighter());
这是精简版 HTML,请注意标记的 2 个位置。如果我将上面的函数调用复制粘贴到位置一,它将失败。如果我将上面的函数调用复制粘贴到位置二,它会成功。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="global.js"></script>
<script type="text/javascript">
function showFighter(id) {
var pic = document.getElementById("picture");
var picPath = 'url(images/' + id + '.png)';
pic.style.backgroundImage = (picPath);
}
function initialFighter() {
var fighter = getURLParameter('fighter');
if (typeof(fighter) != "undefined" && fighter != null) {
showFighter(fighter);
} else {
showFighter('Foobar');
}
}
***** LOCATION ONE *****
</script>
</head>
<body>
<header></header>
<nav id="nav"></nav>
<section id="fighters">
<div id="picture"></div>
<div id="text"></div>
<script type="text/javascript">
***** LOCATION TWO *****
</script>
</section>
<footer id="footer"></footer>
</body>
</html>
下面是global.js,这是加载的第一个脚本文件:
请注意,这里有 2 个 addLoadEvent(func) 调用,它们成功了(不要 运行 直到 html 元素存在之后)尽管实际上高于其他一切。
function addLoadEvent(func) {
var prevOnLoad = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (prevOnLoad) {
prevOnLoad();
}
func();
}
}
}
function loadFile(id, filename) {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById(id).innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open('GET', filename, true);
xmlhttp.send();
}
addLoadEvent(loadFile('nav', 'nav.txt'));
addLoadEvent(loadFile('footer', 'footer.txt'));
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
}
addLoadEvent
的参数应该是一个函数,它将在 onload
回调期间被调用。您立即调用该函数,并传递其 return 值,因此该函数不会等待 onload
事件,并且您会收到错误,因为元素不在 DOM 然而。应该是:
addLoadEvent(function() { loadFile('nav', 'nav.txt'); });
addLoadEvent(function() { loadFile('footer', 'footer.txt'); });
addLoadEvent(initialFighter);
您不需要 initialFighter
的匿名包装函数,因为它不接受任何参数。您只需要省去 ()
,这样您就可以传递对函数的引用,而不是立即调用函数。
此外,您可以简单地使用 addEventListener
,而不是通过保存旧值并在新函数中调用它来链接 onload
事件处理程序,因为它们会自动添加到侦听器列表中更换它:
function addLoadEvent(func) {
window.addEventListener("load", func);
}
解决方案:我将排队机制调用到 window.onload 的方式似乎有问题。
序言 - 我很高兴看到我被标记为重复,解决方案是使用 window.onload,这是我已经在这里使用的东西。一些评论指出了我从另一个 Whosebug 解决方案中获得的 queue 可能存在的问题,但由于缺乏详细说明而让我一无所知。
问题:如果我在head中进行函数调用,它会失败。如果我在 body 中进行函数调用,它会成功。为什么?
扩展:为什么调用失败调用上方的 global.js 中的同一函数会成功?
我有一些 javascript 创建了一个 onload "queue" 类型(global.js 中的函数 addLoadEvent)。当调用 onload 时,调用此函数会添加到 queue。
除此之外,我发现如果某个脚本函数位于头部而不是 body,则它会失败。我不明白为什么,因为所需的一切(其他 js 函数)都在函数调用本身之上加载,并且直到 onload 才触发对该函数的实际调用,确保存在必要的 html 元素.
加载顺序:
- html 文件到头
- global.js - 包括 addLoadEvent(func)
- addLoadEvent x2(成功)
- head 中的内联脚本 - 包括 initialFighter()
- addLoadEvent(位置一 - 失败)
- html 头部后的文件
- addLoadEvent(位置二 - 成功)
- onload 触发 queued 次调用
为了这个问题的目的,根据它的位置失败或成功的函数调用如下。
addLoadEvent(initialFighter());
这是精简版 HTML,请注意标记的 2 个位置。如果我将上面的函数调用复制粘贴到位置一,它将失败。如果我将上面的函数调用复制粘贴到位置二,它会成功。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="global.js"></script>
<script type="text/javascript">
function showFighter(id) {
var pic = document.getElementById("picture");
var picPath = 'url(images/' + id + '.png)';
pic.style.backgroundImage = (picPath);
}
function initialFighter() {
var fighter = getURLParameter('fighter');
if (typeof(fighter) != "undefined" && fighter != null) {
showFighter(fighter);
} else {
showFighter('Foobar');
}
}
***** LOCATION ONE *****
</script>
</head>
<body>
<header></header>
<nav id="nav"></nav>
<section id="fighters">
<div id="picture"></div>
<div id="text"></div>
<script type="text/javascript">
***** LOCATION TWO *****
</script>
</section>
<footer id="footer"></footer>
</body>
</html>
下面是global.js,这是加载的第一个脚本文件:
请注意,这里有 2 个 addLoadEvent(func) 调用,它们成功了(不要 运行 直到 html 元素存在之后)尽管实际上高于其他一切。
function addLoadEvent(func) {
var prevOnLoad = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
if (prevOnLoad) {
prevOnLoad();
}
func();
}
}
}
function loadFile(id, filename) {
var xmlhttp;
if (window.XMLHttpRequest) {
xmlhttp=new XMLHttpRequest();
}
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4 && xmlhttp.status==200) {
document.getElementById(id).innerHTML=xmlhttp.responseText;
}
}
xmlhttp.open('GET', filename, true);
xmlhttp.send();
}
addLoadEvent(loadFile('nav', 'nav.txt'));
addLoadEvent(loadFile('footer', 'footer.txt'));
function getURLParameter(name) {
return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [null, ''])[1].replace(/\+/g, '%20')) || null;
}
addLoadEvent
的参数应该是一个函数,它将在 onload
回调期间被调用。您立即调用该函数,并传递其 return 值,因此该函数不会等待 onload
事件,并且您会收到错误,因为元素不在 DOM 然而。应该是:
addLoadEvent(function() { loadFile('nav', 'nav.txt'); });
addLoadEvent(function() { loadFile('footer', 'footer.txt'); });
addLoadEvent(initialFighter);
您不需要 initialFighter
的匿名包装函数,因为它不接受任何参数。您只需要省去 ()
,这样您就可以传递对函数的引用,而不是立即调用函数。
此外,您可以简单地使用 addEventListener
,而不是通过保存旧值并在新函数中调用它来链接 onload
事件处理程序,因为它们会自动添加到侦听器列表中更换它:
function addLoadEvent(func) {
window.addEventListener("load", func);
}