2012-01-13 69 views
2

我一直在用document.write和onLoad函数挣扎。document.write,onload和可变范围问题

如果你考虑一个JS代码,像这样的=>

window.i = 0; 
console.log(i + " //should be 0"); 

document.write("<scr"+"ipt onLoad='onA1Ready()' src='a1.js'><\/sc"+"ript>"); 

function onA1Ready(){ 
    document.write("<scr"+"ipt onLoad='onA2Ready()' src='a2.js'><\/sc"+"ript>"); 
} 

function onA2Ready(){ 
    console.log(i + " //should be 2"); 
} 

和a1.js beeing这样=>

i++; 
console.log(i + " //should be 1"); 

和a2.js beeing颇为相似=>

i++; 
console.log(i + " //should be 2"); 

我期望最后的控制台输出等于2,但是这里是我从控制台中得到的=>

0 //should be 0  test.js (line 2) 
1 //should be 1  a1.js (line 2) 
i is not defined ERROR i++; a2.js (line 1) 
onA2Ready is not defined 

我想这个问题是范围相关的,但我不知道如何。

如果您有任何关于这里发生了什么的想法,那将是非常棒的。

回答

1

我在Chrome 16上测试过,一切按预期运行。但是,在最新的FF中,我得到了你所描述的错误。

我的建议是停止使用邪恶document.write()动态加载脚本。而是使用DOM方法。我已经写了一个小功能myLoader(),可以帮助你

window.i = 0; 
console.log(i + " //should be 0"); 

var myLoader = function(filename, fun) { 
    var head = document.getElementsByTagName('head')[0], 
     script = document.createElement('script'); 
    script.type= 'text/javascript'; 
    script.src = filename; 
    if(typeof fun === 'function'){ script.onload = fun; } 
    head.appendChild(script); 
}; 


myLoader('a1.js', function(){ 
    myLoader('a2.js', function() { 
    console.log(i + " //should be 2"); 
    }); 
}); 

试试吧。

输出I得到

0 //should be 0   a0.js (line 2) 
1 //should be 1   a1.js (line 2) 
2 //should be 2   a2.js (line 2) 
2 //should be 2   a0.js (line 17) 
+0

似乎很大,我给它一个尝试 非常感谢 – Erwin 2012-01-13 08:29:59

+0

伟大的作品再次感谢 – Erwin 2012-01-13 08:33:40

+0

记得投票这是你的答案;。!) – jaime 2012-01-13 08:34:11

1

首先我会强烈建议不要使用document.write。这是混乱和不必要的。

添加脚本标签,因此是更好的处理:

var addScriptWithOnLoad = function(src, fn) { 
    var s = document.createElement('script'); 
    s.setAttribute('type', 'text/javascript'); 
    s.setAttribute('src', src); 
    s.onload = fn; 
    document.head.appendChild(s); 
}; 

接下来,你真的不应该使用这样的全球范围内,你是依靠浏览器踢得好看,这是从来没有一个安全的赌注。你应该在功能之间传递数据。然而,这有点超出了这个答案的范围。

以下脚本标签,放置在web page的头部,产生你想要的结果

<script type="text/javascript"> 
    window.i = 0; 
    var addJS = function(src, fn) { 
     var s = document.createElement('script'); 
     s.setAttribute('src', src); 
     s.setAttribute('type', 'text/javascript'); 
     s.onload = fn; 
     document.head.appendChild(s); 
    }; 

    console.log(i + " //should be 0"); 

    var fn1 = function() { 
     console.log(); 
     addJS('a2.js', fn2); 
    }; 

    var fn2 = function() { 
     console.log(i + " //should be 2"); 
    }; 

    addJS('a1.js', fn1); 
</script> 
+0

我尝试以下 'window.i = 0; document.write(“<\/sc"+"ript>”); function onA1Ready(){ \t document.write(“<\/sc"+"ript>”); } function onA2Ready(){ \t console.log(window。i +“// onA2Ready”); }' with a1.js => 'window.i ++; console.log(window.i +“//a1.js”);' and a2.js => 'window.i ++; 的console.log(window.i + “//a2.js”);' 控制台日志此=> '的NaN // a2.js a2.js(线2) onA2Ready不defined' – Erwin 2012-01-13 08:14:26

+0

关于全球范围,我不会在实际项目中这样做,这个片段只是为了在这里展示我的问题。无论如何,你的解决方案很好,与jm相当 - 我想。再次感谢,Erwin – Erwin 2012-01-13 10:50:25

0

我怀疑onA1Ready()被调用的onLoad其写入到被调用的onLoad另一个函数,它从来没有被称为该文件已被加载。

+0

嗨,感谢您的帮助,我是一个新手用javascript :( 控制台输出说:onA2Ready没有定义,是不是说,功能beeing叫,但不知何故不可见?那个特定的范围内 – Erwin 2012-01-13 08:17:35