如何加载和使用/动态调用JavaScript
我需要动态加载JavaScript文件,然后访问其内容。
文件test.js
test = function () {
var pub = {}
pub.defult_id = 1;
return pub;
}()
在这种情况下,它有效:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="/test.js"></script>
</head>
<body>
<script type="text/javascript">
console.log(test.defult_id);
</script>
</body>
</html>
但我需要动态加载它,并且这样它不起作用:
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript">
function loadjs(file) {
var script = document.createElement("script");
script.type = "application/javascript";
script.src = file;
document.body.appendChild(script);
}
loadjs('test.js');
console.log(test.defult_id);
</script>
</body>
</html>
错误: Uncaught ReferenceError: test is not defined(…)
你可以这样做:
function loadjs(file) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = file;
script.onload = function(){
alert("Script is ready!");
console.log(test.defult_id);
};
document.body.appendChild(script);
}
欲了解更多信息,请阅读本文:https://www.nczonline.net/blog/2009/06/23/loading-javascript-without-blocking/
有一篇很值得一读的文章,值得所有在www.html5rocks.com上的 js脚本加载的人感兴趣 - 深入潜入脚本加载的黑暗水域。
在这篇文章中,在考虑了许多可能的解决方案之后,作者认为将js脚本添加到body元素的末尾是避免js脚本阻止页面呈现的最好方法,从而加快页面加载时间。
但是,作者为那些渴望异步加载和执行脚本的人提出了另一个好的替代解决方案。
考虑到你有四个脚本命名为script1.js, script2.js, script3.js, script4.js
那么你可以通过应用async = false来实现 :
[
'script1.js',
'script2.js',
'script3.js',
'script4.js'
].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
script.async = false;
document.head.appendChild(script);
});
现在, Spec说 :一起下载,尽快下载完成。
Firefox <3.6,Opera说:我不知道这个“异步”是什么,但是我只是按照它们添加的顺序执行通过JS添加的脚本。
Safari 5.0说:我理解“异步”,但不明白将其设置为“假”与JS。 我会尽快按照任何顺序执行脚本。
IE <10表示:不知道“异步”,但有一个解决方法使用“onreadystatechange”。
其他的一切都是这样说的:我是你的朋友,我们将在书中这样做。
现在,完整的代码与IE <10解决方法:
var scripts = [
'script1.js',
'script2.js',
'script3.js',
'script4.js'
];
var src;
var script;
var pendingScripts = [];
var firstScript = document.scripts[0];
// Watch scripts load in IE
function stateChange() {
// Execute as many scripts in order as we can
var pendingScript;
while (pendingScripts[0] && pendingScripts[0].readyState == 'loaded') {
pendingScript = pendingScripts.shift();
// avoid future loading events from this script (eg, if src changes)
pendingScript.onreadystatechange = null;
// can't just appendChild, old IE bug if element isn't closed
firstScript.parentNode.insertBefore(pendingScript, firstScript);
}
}
// loop through our script urls
while (src = scripts.shift()) {
if ('async' in firstScript) { // modern browsers
script = document.createElement('script');
script.async = false;
script.src = src;
document.head.appendChild(script);
}
else if (firstScript.readyState) { // IE<10
// create a script and add it to our todo pile
script = document.createElement('script');
pendingScripts.push(script);
// listen for state changes
script.onreadystatechange = stateChange;
// must set src AFTER adding onreadystatechange listener
// else we’ll miss the loaded event for cached scripts
script.src = src;
}
else { // fall back to defer
document.write('<script src="' + src + '" defer></'+'script>');
}
}
稍后的一些技巧和缩小,它是362字节
!function(e,t,r){function n(){for(;d[0]&&"loaded"==d[0][f];)c=d.shift(),c[o]=!i.parentNode.insertBefore(c,i)}for(var s,a,c,d=[],i=e.scripts[0],o="onreadystatechange",f="readyState";s=r.shift();)a=e.createElement(t),"async"in i?(a.async=!1,e.head.appendChild(a)):i[f]?(d.push(a),a[o]=n):e.write("<"+t+' src="'+s+'" defer></'+t+">"),a.src=s}(document,"script",[
"//other-domain.com/1.js",
"2.js"
])
Dinamically加载JS文件是异步的,因此为了确保在调用某个函数之前加载脚本,请在脚本中使用onload事件:
function loadjs(file) {
var script = document.createElement("script");
script.type = "application/javascript";
script.onload=function(){
//at this tine the script is loaded
console.log("Script loaded!");
console.log(test);
}
script.src = file;
document.body.appendChild(script);
}
链接地址: http://www.djcxy.com/p/7325.html