script元素相关知识

本文介绍了,script元素的属性、动态加载js的方法、script标签在文档放置位置建议。
文章大纲
js是阻塞式的语言。
一般,页面中<script>标签出现,会使整个页面因脚本加载、解析、运行而出现等待,页面的下载和解析过程必须停下。

script元素属性

type

指示脚本的MIME类型。例如:type="text/javascript"type="text/x-template"

MIME叫多用途互联网邮件扩展(Multipurpose Internet Mail
Extensions),最初是为了将纯文本格式的电子邮件扩展到可以支持多种信息格式而定制的。后来被应用到多种协议里,包括我们常用的HTTP协议。
MIME的常见形式是一个主类型加一个子类型,用斜线分隔。比如text/html、application/javascript、image/png等。
在访问网页时,MIME type帮助浏览器识别一个HTTP请求返回的是什么内容的数据,应该如何打开、如何显示。

以上来自知乎:https://www.zhihu.com/question/60495696

src

规定外部脚本的url

defer

规定脚本是否延迟执行。适用于外部脚本(ie4~ie7浏览器还适用于内联脚本)。
defer="defer"时,脚本非阻塞式立即下载,和渲染后续文档元素,并行进行(异步),直到页面加载完成才执行脚本,在DOMContentLoaded事件触发之前完成(在window.onload之前执行)。

asyns

非阻塞式立即下载,和渲染后续文档元素,并行进行(异步)。脚本下载完成后,立即执行。仅适用于外部脚本。

charset

定义外部脚本文件中所使用的字符编码。

language

不赞成使用,用type代替。规定脚本语言。

在页面加入script的几种方式

1.用script标签直接插入脚本

当浏览器遇到<script>标签,会停下来,下载外部文件代码(如果存在src引入的外部代码),然后解析并运行这些代码。
此过程,页面解析和用户交互是完全被阻塞的。
可以利用script元素的属性改为非阻塞式。
脚本下载执行和页面其他内容的关系

2.动态加载脚本

动态加载的js脚本,下载时是非阻塞的运行时是阻塞的。

2.1通过设置src属性动态加载脚本(异步)

1
2
3
4
5
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.stype = "text/javascript";
script.src = "https://cdn.bootcss.com/vue/2.5.16/vue.js";
head.appendChild(script);

直到script标签插入文档,才会开始下载脚本。

2.2通过文本节点插入到script标签中(同步、低版本ie不支持)

1
2
3
4
5
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.stype = "text/javascript";
script.appendChild(document.createTextNode("var a = 1;"));
head.appendChild(script);

script标签插入文档,脚本立即执行。

2.3通过script标签text属性插入(同步)

IE8-浏览器将<script>元素视为一个特殊的元素,不允许DOM访问其子节点,使用appendChild()方法或innerHTML属性都会报错

1
2
3
4
5
var head = document.getElementsByTagName('head')[0];
var script = document.createElement('script');
script.stype = "text/javascript";
script.text = "var a = 1;";
head.appendChild(script);

script标签插入文档,脚本立即执行。

2.4通过ajax插入脚本(异步)

1
2
3
4
5
6
7
8
9
10
11
12
13
var xhr = new XMLHttpRequest();
xhr.open('get','file1.js',true);
xhr.onreadyStateChange = function(){
if(xhr.readyState === 4){
if(xhr.status >= 200 && xhr.status < 300 || xhr.status === 304){
var script = document.createElement('script');
script.type = 'text/javascript';
script.text = xhr.responseText;
document.getElementsByTagName('head')[0].appendChild('script');
}
}
}
xhr.send(null);

js脚本必须与页面是同一个域。script标签插入文档,脚本立即执行。

2.5通过jq方法getScript插入脚本(异步)

通过HTTP GET形式的加载JavaScript文件并运行它。

1
2
3
$.getScript('file1.js',function(){
alert('load');
})

等同于

1
2
3
4
5
6
7
8
$.ajax({
url:'file1.js',
type:'get',
dataType:'script',
success:function(){
alert('load');
}
})

支持跨域脚本文件。
异步添加脚本,访问该脚本的变量或函数时,应在回调函数中进行。

加载脚本并使用脚本代码的方法封装

src引入js脚本封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function getUrlJs(url,callback){
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
if(typeof callback === 'function'){
script.onload = script.onreadyStateChange = function(){

/*
* !script.readyState判断为现代浏览器
* script.readyState和script.readyState判断为ie低版本浏览器
*/
if(!script.readyState || script.readyState === 'load' || script.readyState === 'complete'){
script.onload = script.onreadyStateChange = null;
callback();
}
}
}
document.getElementsByTagName('head')[0].appendChild(script);
}

ajax引入js脚本封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function getAjaxJs(url,callback){
var xhr = null;
if(window.XMLHttpReques){
xhr = new XMLHttpReques();
}else if(window.ActiveXObject('Microsoft.XMLHTTP')){
xhr = new ActiveXObject('Microsoft.XMLHTTP');
}
xhr.open('get',url,true);
xhr.onreadySateChange = function(){
if(xhr.readyState === 4){
if(xhr.status === 200){
var script = document.createElement('script');
script.type = 'text/javascript';
try{

// 现代浏览器
script.appenChild(document.createTextNode(xhr.responseText))
}catch(){

// ie低版本浏览器
script.text = xhr.responseText;
}
document.getElementsByTagName('head')[0].appendChild(script);
callback();
}
}
}
xhr.send();
}

script标签相关性能优化

  1. 与页面渲染相关(需要在页面渲染之前执行,如和css相关设置rem等)放到head标签内,其他与页面dom操作相关的脚本放到紧邻标签之前。
  2. 适当应用内部脚本(某个页面单独应用时),尤其移动端可减少http请求,优化性能。
  3. 一些需要触发某些条件才执行的脚本(一些事件或者判断客户端等),采用动态加载的方式添加到页面。
  4. 减少script标签引入外部脚本的数量,减少http请求。
坚持原创技术分享,您的支持将鼓励我继续创作!