异步加载JS:
- js加载的缺点:加载工具方法没必要阻塞文档,过得js加载会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作。
- 有些工具方法需要按需加载,用到再加载,不用不加载。
异步加载JS
JavaScript异步加载的三种方案:
1.defer异步加载,但要等到dom文档全部解析完才会被执行。只有IE能用,也可以将代码写到内部。
2.async异步加载,加载完就被执行,async只能加载外部脚本,不能把js写在script标签里。
1.2执行时也不阻塞页面
3.创建script,插入到DOM中,加载完毕之后callBack。
1.defer
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<script type="text/javascript" defer="defer">
//异步加载的JavaScript
//不会阻断HTML和CSS的下载,一起并行下载
</script>
</body>
</html>
2.async
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<script type="text/javascript" async="async" src="xxx.js">
</script>
</body>
</html>
3.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<script type="text/javascript">
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "xxx.js";
</script>
</body>
</html>
现在只会去下载,不会执行,当你在添加上document.head.appendChild(script);的时候才会去执行。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<script type="text/javascript">
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "xxx.js";
document.head.appendChild(script);
</script>
</body>
</html>
我如果把document.head.appendChild(script);删除时,js.js文件现在已经下载了,但是没有js.js里面的内容并没有被执行!!
现在我执行这个test();能执行吗?
不行吧!也不是真的不行
我让他在一秒之后执行这个函数,可以被执行。
那为什么一秒钟之后可以被执行,当前执行不了吧?是不是当前还没有下载完!
程序执行以微妙计的。
所以现在有没有一个东西能够提示咱们,js文件下载完了,然后才去调用他的方法。
这个就能确保下载完成之后再去执行test();
onload兼容:safari,Chrome,Firefox,Opera都兼容
IE:script.reanyState(状态码),他会动态的去改变里面的东西,比如一开始script.reanyState=”loading”,当下载完成之后,会把loading改成loaded或者complete。
咱们把他们封装成一个函数:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<script type="text/javascript">
function loadScript(url,callback){
var script = document.createElement("script");
script.type = "text/javascript";
script.src = url;
if(script.readyState){
script.onreadystatechange = function(){
if(script.readyState == "complete" || script.readyState == "loaded"){
callback();
}
}
}else{
script.onload = function(){
callback();
}
}
document.head.appendChild(script);
}
</script>
</body>
</html>
现在有一个问题:onreadystatechange监听的是readyState的变化,readyState一变,他就触发这个东西,你说有没有这种情况,我的电脑在服务器旁边插了一根10m宽的光线,比本机存储还要快,script.src = url;的时候,瞬间就把资源下载完了,下载完成之后,script.readyState瞬间就便到了最终的状态了,那下面再绑定onreadystatechange还有意义吗?人家瞬间就到了终止的状态了,就不会再改变了。
改:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<script type="text/javascript">
function loadScript(url,callback){
var script = document.createElement("script");
script.type = "text/javascript";
if(script.readyState){
script.onreadystatechange = function(){
if(script.readyState == "complete" || script.readyState == "loaded"){
callback();
}
}
}else{
script.onload = function(){
callback();
}
}
script.src = url;
document.head.appendChild(script);
}
</script>
</body>
</html>
我先执行这个绑定事件,然后再加载这个文件。
但是:
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<script type="text/javascript">
function loadScript(url,callback){
var script = document.createElement("script");
script.type = "text/javascript";
if(script.readyState){
script.onreadystatechange = function(){
if(script.readyState == "complete" || script.readyState == "loaded"){
callback();
}
}
}else{
script.onload = function(){
callback();
}
}
script.src = url;
document.head.appendChild(script);
}
loadScript("js.js",test);
</script>
</body>
</html>
怎么回事?
执行顺序是先解析function loadScript(url,callback){},不会看里面是什么,然后再执行loadScript("js.js",test);去导致function的执行,所以你先塞进去了一个test,他都不知道是什么吧!
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>abraham</title>
</head>
<body>
<script type="text/javascript">
function loadScript(url,callback){
var script = document.createElement("script");
script.type = "text/javascript";
if(script.readyState){
script.onreadystatechange = function(){
if(script.readyState == "complete" || script.readyState == "loaded"){
callback();
}
}
}else{
script.onload = function(){
callback();
}
}
script.src = url;
document.head.appendChild(script);
}
loadScript("js.js",function(){
test();
});
</script>
</body>
</html>
这叫做函数的引用,我传一个匿名函数进去,函数里面的函数体叫做test();
函数引用在读的时候不会读里面的代码,在执行的时候才会去读。