使用全局JavaScript变量和Internet Explorer的YepNope/Modernizer回调
有人能解释为什么在InternetExplorer中,代码示例1不工作,而代码示例2工作吗 代码1(非功能性) 代码2(功能性) bar.js 它可以在其他浏览器中正常工作。我试着将这些块移到页眉部分以及页面下方。我还尝试将回调的内容包装在使用全局JavaScript变量和Internet Explorer的YepNope/Modernizer回调,javascript,internet-explorer,global-variables,modernizr,yepnope,Javascript,Internet Explorer,Global Variables,Modernizr,Yepnope,有人能解释为什么在InternetExplorer中,代码示例1不工作,而代码示例2工作吗 代码1(非功能性) 代码2(功能性) bar.js 它可以在其他浏览器中正常工作。我试着将这些块移到页眉部分以及页面下方。我还尝试将回调的内容包装在$(document).ready()中,但没有一个能处理代码1 我得到的具体错误是: 脚本5009:«initBar»est indéfini 这几乎就像是在资源加载完成之前执行回调一样,但如果是这样,那么为什么代码示例2可以工作呢 我还将注意到,在刷新时,
$(document).ready()
中,但没有一个能处理代码1
我得到的具体错误是:
脚本5009:«initBar»est indéfini
这几乎就像是在资源加载完成之前执行回调一样,但如果是这样,那么为什么代码示例2可以工作呢
我还将注意到,在刷新时,页面加载良好(很可能是因为资源已缓存),但在清除缓存后,页面也会加载良好。在清除缓存后,我必须重新启动浏览器会话以重现问题
更新:
这个问题不仅仅局限于函数。加载的JS文件中定义的任何全局变量似乎都无法直接访问。如果我在页面顶部加载CSS,而不是异步加载其他资源,也会发生这种情况。事实上,我也注意到了一些以这种方式加载的jQuery插件的问题
更新2:
下面是根据下面的调试说明输出的console.log()。为了说明这一点,我将bar改为对象而不是函数
Internet Explorer:
因此,complete
函数似乎在定义bar
之前执行。我觉得奇怪的是,window.bar
也没有定义,但仍然可以工作
火狐
铬
Firefox和Chrome似乎都在以正确的顺序加载和执行资源。首先,您应该知道modernizr中的.load()
来自于yepnope库,因此您可以在这里找到它的详细文档
以下是我能想到的在不同浏览器中可能不同的东西:
加载脚本的确切时间,以及调用complete()
函数的时间
浏览器中的缓存(这可能会影响加载定时)
因为您是通过将其分配给变量而不是常规的函数initBar()
定义来定义initBar
,所以在执行该行代码之前,函数将不存在,而函数initBar()
将在脚本解析时存在
确保您使用的是1.5版或更高版本的yepnope加载库(我不知道与哪个Modernizer版本相对应。.load()
的yepnope文档中说:“在1.5之前的yepnope版本中,[调用完整函数时]可能会不时变化”
在调用完整回调之前,yepnope库可能不会等待.css文件加载,除非您有加载项。我不知道这是否会影响整个完整计时,或者我注意到您的加载列表中确实有.css文件
因此,我建议调试以下内容:
1) 将initBar定义更改为:
function initBar() {
// code here
}
2) 确保initBar定义在正确的范围内,并且可以从其他代码访问。注意其他功能(onload、document.ready等)中可能导致无法访问的内容
3) 插入一些类似这样的console.log()
语句以执行一些定时调试:
console.log("before .load() called");
Modernizr.load([
{
load: [
'../includes/css/foo.css',
'../includes/js/foo.js',
'../includes/js/bar.js'
],
complete: function() {
console.log("before initBar() called");
console.log("typeof initBar = " + typeof initBar);
console.log("typeof window.initBar = " + typeof window.initBar);
initBar();
console.log("after initBar() called");
}
}
]);
console.log("before initBar() defined");
function initBar() {
// code here
}
然后,看看事情发生的顺序和陈述的类型。这里的想法是试图找出事情是否以错误的顺序执行,或者范围是否错误
4) 尝试单独加载.css文件,这样就不会影响.js的加载
这里有一个替换脚本,可以动态加载多个脚本来替换Modernizer buggy.load()
代码。这一个并行加载它们。这仅适用于脚本文件(尽管相同的概念可用于.css
文件)
function loadScriptsInParallel(scripts, completeCallback) {
var head = document.getElementsByTagName('head')[0];
var remaining = scripts.length, i, scriptTag;
function complete() {
// make sure it's not called again for this script
this.onreadystatechange = this.onload = function() {};
// decrement remaining count and check if all are done
--remaining;
if (remaining === 0) {
// all are done call the callback
completeCallback();
}
}
for (var i = 0; i < scripts.length; i++) {
scriptTag = document.createElement('script');
scriptTag.type = 'text/javascript';
scriptTag.src = scripts[i];
// most browsers
scriptTag.onload = complete;
// IE 6 & 7
scriptTag.onreadystatechange = function() {
if (this.readyState == 'complete') {
complete.apply(this, arguments);
}
}
head.appendChild(scriptTag);
}
}
工作演示:
如果需要按顺序加载它们(由于它们之间的依赖关系,一个接一个),则可以使用以下方法:
function loadScriptsInSequence(scripts, completeCallback) {
var head = document.getElementsByTagName('head')[0];
var remaining = scripts.length, i = 0;
function loadNext() {
var scriptTag = document.createElement('script');
scriptTag.type = 'text/javascript';
scriptTag.src = scripts[i++];
// most browsers
scriptTag.onload = complete;
// IE 6 & 7
scriptTag.onreadystatechange = function() {
if (this.readyState == 'complete') {
complete.apply(this, arguments);
}
}
head.appendChild(scriptTag);
}
function complete() {
// make sure it's not called again for this script
this.onreadystatechange = this.onload = function() {};
// decrement remaining count and check if all are done
--remaining;
if (remaining === 0) {
// all are done call the callback
completeCallback();
} else {
loadNext();
}
}
loadNext();
}
工作演示:首先,您应该知道Modernizer中的.load()
来自于yepnope库,因此您可以在这里找到它的详细文档
以下是我能想到的在不同浏览器中可能不同的东西:
加载脚本的确切时间,以及调用complete()
函数的时间
浏览器中的缓存(这可能会影响加载定时)
因为您是通过将其分配给变量而不是常规的函数initBar()
定义来定义initBar
,所以在执行该行代码之前,函数将不存在,而函数initBar()
将在脚本解析时存在
确保您使用的是1.5版或更高版本的yepnope加载库(我不知道与哪个Modernizer版本相对应。.load()
的yepnope文档中说:“在1.5之前的yepnope版本中,[调用完整函数时]可能会不时变化”
在调用完整回调之前,yepnope库可能不会等待.css文件加载,除非您有加载项。我不知道这是否会影响整个完整计时,或者我注意到您的加载列表中确实有.css文件
因此,我建议调试以下内容:
1) 将initBar定义更改为:
function initBar() {
// code here
}
2) 确保initBar定义在正确的范围内,并且可以从
before .load() called
before bar defined
before bar accessed
typeof bar = object
typeof window.bar = object
function initBar() {
// code here
}
console.log("before .load() called");
Modernizr.load([
{
load: [
'../includes/css/foo.css',
'../includes/js/foo.js',
'../includes/js/bar.js'
],
complete: function() {
console.log("before initBar() called");
console.log("typeof initBar = " + typeof initBar);
console.log("typeof window.initBar = " + typeof window.initBar);
initBar();
console.log("after initBar() called");
}
}
]);
console.log("before initBar() defined");
function initBar() {
// code here
}
function loadScriptsInParallel(scripts, completeCallback) {
var head = document.getElementsByTagName('head')[0];
var remaining = scripts.length, i, scriptTag;
function complete() {
// make sure it's not called again for this script
this.onreadystatechange = this.onload = function() {};
// decrement remaining count and check if all are done
--remaining;
if (remaining === 0) {
// all are done call the callback
completeCallback();
}
}
for (var i = 0; i < scripts.length; i++) {
scriptTag = document.createElement('script');
scriptTag.type = 'text/javascript';
scriptTag.src = scripts[i];
// most browsers
scriptTag.onload = complete;
// IE 6 & 7
scriptTag.onreadystatechange = function() {
if (this.readyState == 'complete') {
complete.apply(this, arguments);
}
}
head.appendChild(scriptTag);
}
}
loadScriptsInParallel([
'../includes/js/foo.js',
'../includes/js/bar.js'
], function() {
// put code here for when all scripts are loaded
initBar();
});
function loadScriptsInSequence(scripts, completeCallback) {
var head = document.getElementsByTagName('head')[0];
var remaining = scripts.length, i = 0;
function loadNext() {
var scriptTag = document.createElement('script');
scriptTag.type = 'text/javascript';
scriptTag.src = scripts[i++];
// most browsers
scriptTag.onload = complete;
// IE 6 & 7
scriptTag.onreadystatechange = function() {
if (this.readyState == 'complete') {
complete.apply(this, arguments);
}
}
head.appendChild(scriptTag);
}
function complete() {
// make sure it's not called again for this script
this.onreadystatechange = this.onload = function() {};
// decrement remaining count and check if all are done
--remaining;
if (remaining === 0) {
// all are done call the callback
completeCallback();
} else {
loadNext();
}
}
loadNext();
}