How load and use/call dynamically JavaScript

匿名 (未验证) 提交于 2019-12-03 02:29:01

问题:

I need to dynamically load a JavaScript file and then access its content.

File test.js

test = function () {     var pub = {}     pub.defult_id = 1;     return pub; }() 


In this case it works:

<!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> 


But I need to load it dynamically, and that way it does not work:

<!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> 


Error: Uncaught ReferenceError: test is not defined(…)

回答1:

You could do it like this:

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);  } 

For more information read this article : https://www.nczonline.net/blog/2009/06/23/loading-javascript-without-blocking/



回答2:

There is a great article which is worth reading for all the guys interesting in js script loading in www.html5rocks.com - Deep dive into the murky waters of script loading .

In that article after considering many possible solutions, the author concluded that adding js scripts to the end of body element is the best possible way to avoid blocking page rendering by js scripts thus speeding page loading time.

But, the author propose another good alternate solution for those people who are desperate to load and execute scripts asynchronously.

Considering you've four scripts named script1.js, script2.js, script3.js, script4.js then you can do it with applying 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); }); 

Now, Spec says: Download together, execute in order as soon as all download.

Firefox < 3.6, Opera says: I have no idea what this “async” thing is, but it just so happens I execute scripts added via JS in the order they’re added.

Safari 5.0 says: I understand “async”, but don’t understand setting it to “false” with JS. I’ll execute your scripts as soon as they land, in whatever order.

IE < 10 says: No idea about “async”, but there is a workaround using “onreadystatechange”.

Everything else says: I’m your friend, we’re going to do this by the book.

Now, the full code with IE < 10 workaround:

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>');   } } 

A few tricks and minification later, it’s 362 bytes

!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" ]) 


回答3:

Dinamically loading JS files is asynchronous, so to ensure your script is loaded before calling some function inside, use the onload event in script:

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);         } 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!