YepNope/Modernizr 回调,包含全局 JavaScript 变量和 Internet Explorer
YepNope/Modernizr callbacks with global JavaScript variables and Internet Explorer
谁能解释为什么在Internet Explorer中,代码示例1不起作用,而代码示例2不起作用?
代码 1(无法正常工作(
Modernizr.load([
{
load: [
'../includes/css/foo.css',
'../includes/js/foo.js',
'../includes/js/bar.js'
],
complete: function() {
initBar();
}
}
]);
代码 2(功能(
Modernizr.load([
{
load: [
'../includes/css/foo.css',
'../includes/js/foo.js',
'../includes/js/bar.js'
],
complete: function() {
window.initBar();
}
}
]);
酒吧.js
var initBar = function() {
// code here
};
它在其他浏览器中工作正常。我尝试将块移动到头部以及页面下方。我也尝试将回调的内容包装在 $(document).ready()
中,但没有一个使用代码 1。
我特别遇到的错误是:
SCRIPT5009: « initBar » est indéfini
这几乎就像在资源完成加载之前执行回调一样,但如果是这种情况,那么为什么代码示例 2 有效?
我还会注意到,刷新时页面加载正常(很可能是由于资源被缓存的事实(,但在清除缓存后它也能加载正常。清除缓存后,我必须重新启动浏览器会话才能重现问题。
更新:这个问题不仅仅是功能。加载的 JS 文件中定义的任何全局变量似乎都无法直接访问。如果我在页面顶部加载 CSS,而不是异步加载其他资源,也会发生这种情况。事实上,我也注意到一些以这种方式加载的jQuery插件存在此问题。
更新 2:以下是根据以下调试说明console.log()
输出。为了说明这一点,我将 bar 更改为对象而不是函数。
IE浏览器:
HTML1300: Une navigation s’est produite.
Fichier : test18.php
before .load() called
before bar accessed
typeof bar = undefined
typeof window.bar = undefined
SCRIPT5009: « bar » est indéfini
Fichier : test18.js, ligne : 14, colonne : 13
before bar defined
因此,complete
函数似乎在定义bar
之前执行。我觉得很奇怪,window.bar
也是未定义的,但有效......
火狐
[02:10:46,448] "before .load() called"
[02:10:47,184] "before bar defined"
[02:10:47,184] "before bar accessed"
[02:10:47,184] "typeof bar = object"
[02:10:47,184] "typeof window.bar = object"
铬
before .load() called
before bar defined
before bar accessed
typeof bar = object
typeof window.bar = object
Firefox和Chrome似乎都以正确的顺序加载和执行资源。
首先,您应该知道 modernizr 中的.load()
来自 yepnope 库,因此您可以在此处找到它的详细文档。
以下是我能想到的不同浏览器中可能有所不同的事情:
-
加载脚本的确切时间,从而调用
complete()
函数的时间。 -
浏览器中的缓存(可能会影响加载计时(。
-
由于您通过将
initBar
赋值给变量而不是常规function initBar()
定义来定义因此,在该行代码执行之前,该函数将不存在,而function initBar()
将在脚本解析时存在。 -
确保 yepnope 加载库的版本为 1.5 或更高版本(我不知道对应于哪个 modernizr 版本。
.load()
的yepnope文档是这样说的:"在1.5之前的yepnope版本中,[调用完整函数时]可能会不时变化"。 -
此页面上有注释,除非存在加载项,否则 yepnope 库可能不会等待.css文件加载后调用完整的回调。 我不知道这是否抛弃了整个完整的时间,或者我注意到您的加载列表中确实有.css个文件。
因此,这是我建议调试的内容:
1( 将你的初始化栏定义更改为:
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加载。
这是一个替换脚本
,可以动态加载多个脚本来替换 modernizr 错误.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);
}
}
示例用法:
loadScriptsInParallel([
'../includes/js/foo.js',
'../includes/js/bar.js'
], function() {
// put code here for when all scripts are loaded
initBar();
});
工作演示:http://jsfiddle.net/jfriend00/qs44R/
如果您需要按顺序加载它们(由于它们之间的依赖关系,一个接一个(,那么您可以使用以下内容:
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();
}
工作演示:http://jsfiddle.net/jfriend00/9aVLW/
- 调用类向后变量 (JavaScript)
- 初始化父类中的变量(JavaScript/CoffeeScript 习语)
- 可以'找不到变量javascript错误
- 输出数组变量javascript
- 自提交表单访问变量javascript
- 将变量 javascript 添加到用于旋转图像的链接中
- 在文本字段中显示保存的本地存储变量 - javascript
- 将变量添加到变量 JavaScript 中
- 获取要在变量 JavaScript 中使用的用户输入值
- 如何在变量 Javascript 中删除双引号
- 使用变量 javascript 从 json 文件中获取数据
- 读取输入和打印变量 - JavaScript 和 HTML 4.01
- 传递 PHP 变量 JavaScript 窗口位置
- 重置变量 JavaScript
- 变量 JavaScript 中的变量
- 尝试使用多个函数时无法使用全局变量 - JavaScript - 初学者
- 如何按值将数组分配给另一个变量 JavaScript
- setTimout 搞砸了变量 JavaScript
- 用内部函数变量更改外部函数变量?Javascript
- 根据变量 JavaScript 增加