javascript是一门弱数据类型的语言,从执行机制上来讲是单线程,即代码会一行一行自上而下往下执行。通常,我们日常生活中所讲的 同步 表示的是同一个时间段在做几件相互独立的事, 异步 表示做完一件事再去做另一件事,但是在计算机的世界中,同步异步的概念恰好与现实世界中相反,异步表示同一个时间段做几件相互独立的事。
异步加载js表示,浏览器在加载js文件的时候,也在进行着其他的工作,如渲染页面等
异步加载js的优点?
通常来讲,因为javascript是单线程的执行机制,所以浏览器是同步加载js代码的,但是一旦遇到网速不好,或者加载的js文件过大的话,往往会造成页面阻塞,整个网站将等待js加载而不进行后续的渲染工作,十分影响交互体验。所以,通常在这种情况下,异步加载js是一种很好的选择。
特点 :只有IE适用,需等到dom文档全部解析完(dom树生成完,才会被执行)
<script type = 'text/javascript' src = tools.js' defer = 'defer'></script>
<script type = 'text/javascript' src = tools.js' defer ></script>
//注 :当key和value值一样是,直接写key值
特点:加载完就执行,async 只能加载外部脚本,不能把js代码写在script标签里
<script type = 'text/javascript' src = 'tools.js' defer></script>
var script = doccumrnt.createElement('script');
script.type = 'text/javascript';
script.src = 'tools.js';
document.head.appendChild(script);
// 不写这一行,就只能加载,不执行
//tools文件表示如下
function test(){console.log('hello world')
//在页面中引入tools文件,并执行里面的方法
<script script type = 'text/javascript'>
var script = doccumrnt.createElement('script');
script.type = 'text/javascript';
script.src = 'tools.js';
document.head.appendChild(script);
test ()
</script>
Uncaught ReferenceError: test is not defined
这是因为,当程序执行到test()时,前面的script.srd = 'tools.js’还没有下载完成
修改方法1:
<script script type = 'text/javascript'>
var script = doccumrnt.createElement('script');
script.type = 'text/javascript';
script.src = 'tools.js';
document.head.appendChild(script);
setInterval(function(){
test ();
],1000)
</script>
当把函数设置为一秒后执行,即等js文件下载完后再执行,就不报错。
此时,我们想是否是一种方法能提醒我们js文件下载完成了,我们然后再执行函数
<script script type = 'text/javascript'>
var script = doccumrnt.createElement('script');
script.type = 'text/javascript';
script.src = 'tools.js';
script.onload = function (){
test();
}
document.head.appendChild(script);
</script>
script.readyState = 'loading' 最开始的值
script.readyState = 'complete' || 'loaded" 表设计加载完成
监听这个方法的事件:onreadystatechange
<script script type = 'text/javascript'>
var script = doccumrnt.createElement('script');
script.type = 'text/javascript';
script.src = 'tools.js';
script.onreadystatechange = function(){
if(script.readyState == 'complete || script.readyState == 'loaded'){
test();
}
}
</script?
<script script type = 'text/javascript'>
function loadScript(url,callback){
var script = doccumrnt.createElement('script');
script.type = 'text/javascript';
if(script.readyState) {
script.onreadystatechange = function(){
if(script.readyState == 'complete' || script.readyState == 'loaded'){
callback ();
}
}
}else{
script.onload = function(){
callnack();
}
}
script.src = 'url'; // 防止出现网速太快造成事件监听不到变化
document.head.appendChild(script);
}
scriptLoad(tools.js ,test)
此时会出现的问题
Uncaught ReferenceError: test is not defined
这是因为加载函数loadScript是并不会查看里面的代码,等到执行到 scriptLoad(tools.js ,test)时,找不到test
解决方法:把callback 变成字符串形式
方式一:使用eval (不推荐使用)
<script script type = 'text/javascript'>
function loadScript(url,callback){
var script = doccumrnt.createElement('script');
script.type = 'text/javascript';
if(script.readyState) {
script.onreadystatechange = function(){
if(script.readyState == 'complete' || script.readyState == 'loaded'){
eval(callback);
//能把字符串当代码执行
}
}
}else{
script.onload = function(){
eval(callnack);
}
}
script.src = 'url';
document.head.appendChild(script);
}
scriptLoad(tools.js ,'test')
方法二:需要配和js文件来使用
//tools代码文件如下
var tools = {
test :function(){
console.log('hello world')
}
}
<script script type = 'text/javascript'>
function loadScript(url,callback){
var script = doccumrnt.createElement('script');
script.type = 'text/javascript';
if(script.readyState) {
script.onreadystatechange = function(){
if(script.readyState == 'complete' || script.readyState == 'loaded'){
tools[callback]();
}
}
}else{
script.onload = function(){
tools[callback]();
}
}
script.src = 'url';
document.head.appendChild(script);
}
scriptLoad(tools.js ,'test')