6 浏览器对象
6.1 浏览器对象
6.1.1 JavaScript代码嵌入网页的方法
6.1.1.1 直接添加代码块
<script>
// some JavaScript code
</script>
6.1.1.2 加载外部脚本
<script src="example.js"></script>
6.1.1.3 行内代码
也可以在某些元素的事件属性和a元素的href属性中,直接写入JavaScript。
<div onclick="alert('Hello')"></div>
<a href="javascript:alert('Hello')"></a>
6.1.2 外部脚本的加载
6.1.2.1 网页底部加载
网页加载流程是这样的:
- 浏览器开始解析HTML网页
- 解析过程中,发现script标签
- 暂停解析,下载script标签中的外部脚本
- 下载完成,执行脚本
- 恢复往下解析HTML网页
加载外部脚本,会暂停网页执行。因此建议将script标签放在页面底部。这样也避免了在DOM生成之前就调用DOM的错误。
6.1.2.2 多个脚本的加载
多个脚本会同时平行下载,但是却按出现顺序执行。
同一个域名的资源(脚本文件、样式表文件、图片文件),浏览器一般最多同时下载六个。如果是来自不同域名的资源,就没有这个限制。所以,通常把静态文件放在不同的域名之下,以加快下载速度。
6.1.2.3 defer属性
给script增加defer属性后,浏览器不阻塞页面渲染,会继续往下解析HTML网页,同时并行下载script标签中的外部脚本。待浏览器完成解析HTML网页,此时再执行下载的脚本。
<script src="1.js" defer></script>
但是,有的浏览器可能不支持defer。
6.1.2.4 async属性
给script增加async属性后,浏览器不阻塞页面渲染,会继续往下解析HTML网页,同时并行下载script标签中的外部脚本。脚本下载完成,浏览器暂停解析HTML网页,开始执行下载的脚本。脚本执行完毕,浏览器恢复解析HTML网页。
<script src="1.js" async></script>
IE 10支持async属性,低于这个版本的IE都不支持。
一般来说,如果脚本之间没有依赖关系,就使用async属性,如果脚本之间有依赖关系,就使用defer属性。
6.1.2.5 脚本的动态嵌入
除了用静态的script标签,还可以动态嵌入script标签。
['1.js', '2.js'].forEach(function(src) {
var script = document.createElement('script');
script.src = src;
document.head.appendChild(script);
});
6.1.3 JavaScript虚拟机
javascript代码被转为字节码后,并不能直接运行,而是运行在一个虚拟机(也叫JavaScript引擎)之上。
常见的JavaScript虚拟机:
Chakra
V8
6.1.4 单线程模型
JavaScript采用单线程模型,原因是不想让浏览器变得太复杂。
如果有一个任务特别耗时,后面的任务都会等待,造成浏览器“假死”。其实这时候可以挂起处于等待中的任务,先运行排在后面的任务。这种机制就是JavaScript内部采用的Event Loop。
6.1.5 Event Loop
所谓Event Loop,指的是一种内部循环,用来排列和处理事件,以及执行函数。
6.1.6 任务队列
如果有大量的异步任务,它们会在“任务队列”中注册大量的事件。这些事件排成队列,等候进入主线程。
6.2 定时器
6.2.1 setTimeout
setTimeout函数指定过多少毫秒后执行某个函数或某段代码。
它返回定时器的编号,以后可以用来取消这个定时器。
setTimeout('console.log(2)',1000);
setTimeout(f,1000);
setTimeout还允许添加更多的参数:
setTimeout(function(a,b){
console.log(a+b);
},1000,1,1);
6.2.2 setInterval
setInterval函数指定循环(指的是“开始执行”之间的间隔)执行某个函数或某段代码。
<input type="button" onclick="clearInterval(timer)" value="stop">
function f(a){
console.log(a);
}
var timer = setInterval(f, 1000, "Hello World");
如果要实现固定间隔执行代码,不能用setInterval,而是每次执行结束后,使用setTimeout指定下一次执行的具体时间。
<input type="button" onclick="clearInterval(timer)" value="stop">
var timer = setTimeout(function() {
// do something
timer = setTimeout(arguments.callee, 2000);
}, 2000);
6.2.3 clearTimeout(),clearInterval()
用于取消相应的计数器。
6.2.4 运行机制
setTimeout和setInterval的运行机制是,将指定的代码移出本次执行,等到下一轮Event Loop时,再检查是否到了指定时间。如果到了,就执行对应的代码;如果不到,就等到再下一轮Event Loop时重新判断。
每一轮Event Loop时,都会将“任务队列”中需要执行的任务,一次执行完。setTimeout和setInterval都是把任务添加到“任务队列”的尾部。因此,没法保证,setTimeout和setInterval指定的任务,一定会按照预定时间执行。
6.2.5 setTimeout(f,0)
setTimeout(f,0)相当于,一旦本次Event Loop完成就执行。
0毫秒实际上达不到的。根据HTML 5标准,setTimeOut推迟执行的时间最少是4毫秒。
6.3 window对象
6.3.1 概述
JavaScript的所有对象都存在于一个运行环境之中,这个运行环境本身也是对象,称为“顶层对象”。
在浏览器环境中,这个顶层对象就是window对象(w为小写)。所有浏览器环境的全局变量,都是window对象的属性。
6.3.2 window对象的属性
6.3.2.1 window.name属性
用于设置当前浏览器窗口的名字(不是title)。浏览器刷新后,该属性保持不变。
6.3.2.2 window.innerHeight属性,window.innerWidth属性
网页的CSS布局占据的浏览器窗口的高度和宽度
6.3.2.3 window.pageXOffset属性,window.pageYOffset属性
页面的水平/垂直滚动距离
6.3.2.4 iframe元素
iframe元素遵守同源政策,只有当父页面与框架页面来自同一个域名,两者之间才可以用脚本通信
6.3.2.5 Navigator对象
Window对象的Navigator属性是一个包含浏览器相关信息的对象。
1、Navigator.userAgent属性
返回浏览器的User-Agent字符串,用来标示浏览器的种类。
2、navigator.plugins属性
返回一个类似数组的对象,成员是浏览器安装的插件,比如Flash、ActiveX等。
6.3.2.6 screen对象
screen对象包含了显示设备的信息。
screen.height // 1920
screen.width // 1080
可以根据屏幕分辨率,将用户导向不同网页。
6.3.3 window对象的方法
6.3.3.1 URL的编码/解码方法
decodeURI()
decodeURIComponent()
encodeURI()
encodeURIComponent()
6.3.4 window对象的事件
6.3.4.1 window.onerror
脚本发生错误时,会触发window对象的error事件。我们可以通过window.onerror属性对该事件指定回调函数。
6.3.4.2 alert(),prompt(),confirm()
alert 弹出的对话框,只有一个“确定”按钮
prompt 弹出的对话框,在提示文字的下方,还有一个输入框,要求用户输入信息,并有“确定”和“取消”两个按钮。
其返回值:字符串、空(或输入框的默认值)、或者null
var result = prompt('您的年龄?', 25) //25是默认值,可无
confirm 弹出的对话框,除了提示信息之外,只有“确定”和“取消”两个按钮。
返回一个布尔值
var result = confirm("你最近好吗?");
6.4 History对象
浏览器窗口有一个history对象,用来保存浏览历史。
back():后退
forward():前进
go():移动到该整数指定的页面,比如go(1)相当于forward(),go(-1)相当于back()。
6.5 Ajax
6.5.1 XMLHttpRequest对象
XMLHttpRequest对象用于从JavaScript发出HTTP请求,下面是典型用法。
// 新建一个XMLHttpRequest实例对象
var xhr = new XMLHttpRequest();
// 指定通信过程中状态改变时的回调函数
xhr.onreadystatechange = function(){
// 通信成功时,状态值为4
var completed = 4;
if(xhr.readyState === completed){
if(xhr.status === 200){
// 处理服务器发送过来的数据
}else{
// 处理错误
}
}
};
// open方式用于指定HTTP动词、请求的网址、是否异步
xhr.open('GET', '/endpoint', true);
// 发送HTTP请求
xhr.send(null);
6.5.1.1 Open()
open方法用于指定发送HTTP请求的参数
参数1,发送方法。“GET”、“POST”、“PUT”、“DELETE”
参数2,网址
参数3,是否异步
6.5.1.2 setRequestHeader()
setRequestHeader方法用于设置HTTP请求的头信息。
6.5.1.3 send()
send方法用于实际发出HTTP请求。
不带参数,表示HTTP请求只包含头信息,也就是只有URL,例如GET请求;
带有参数,表示还包含具体数据的信息体,例如POST请求。
send方法可以发送许多类型的数据。
void send();
void send(ArrayBuffer data);
void send(Blob data);//Blob类型可以用来发送二进制数据(上传文件)
void send(Document data);
void send(DOMString data);
void send(FormData data); //FormData类型可以用于构造表单数据
6.5.1.4 readyState属性和readyStateChange事件
每次状态(readyState)变化是,都会触发readyStateChange事件。
当状态变为4的时候,表示通信成功,这时就可以处理服务器传送回来的数据。
6.5.1.5 progress事件
上传文件时,XMLHTTPRequest对象的upload属性有一个progress,会不断返回上传的进度。
6.5.1.6 服务器返回的信息
1、status属性
表示返回的HTTP状态码。通信成功的状态码是200。
2、responseText属性
表示服务器返回的文本数据。
6.5.1.7 setRequestHeader方法
用于设置HTTP头信息。
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.setRequestHeader('Content-Length', JSON.stringify(data).length);
xhr.send(JSON.stringify(data));
6.5.1.8 responseType属性
用来指定服务器返回数据(xhr.response)的类型。
'text':返回类型为字符串,这是默认值。
'arraybuffer':返回类型为ArrayBuffer。
'blob':返回类型为Blob。
'document':返回类型为Document。
'json':返回类型为JSON object。
6.5.2 文件上传
通常使用file控件实现文件上传。
file控件的multiple属性,指定可以一次选择多个文件。
<input type="file" id="file-select" name="photos[]" multiple/>
file对象的files返回FileList对象,包含了用户选中的文件。
var files = document.getElementById('file-select').files;
可以使用FormData接口上传,也可以直接使用File API上传。
6.5.3 JSONP
JSONP(JSON with Padding)是JSON的一种“使用模式”,可用于解决浏览器的跨域访问问题。
但 script 元素调用js文件时则不受是否跨域的影响,利用这一点,网页可以得到从其他来源动态产生的 JSON 资料,而这种使用模式就是所谓的 JSONP。
用 JSONP 抓到的资料并不是JSON,而是任意的JavaScript(因为JSON不是合法的js语句,所以要将它放到一个回调方法里),用 JavaScript 直译器执行而不是用 JSON 解析器解析。
6.5.3.1 简单JSONP实现
客户端代码:
<script>
var localHandler = function(data){
alert(data.result);
};
</script>
<script type="text/javascript" src="http://remoteserver.com/remote.js"></script>
服务器端代码:
localHandler({"result":"1"});
6.5.3.2 服务器端动态提供js脚本
客户端代码:
<script>
// 回调函数
var flightHandler = function(data){
alert('票价 ' + data.price + ' 元,' + '余票 ' + data.tickets);
};
var url = "http://remoteserver.com/remote.aspx?code=CA1998&callback=flightHandler";
var script = document.createElement('script');
script.setAttribute('src', url);
document.getElementsByTagName('head')[0].appendChild(script);
</script>
服务器端代码:
flightHandler({
"code": "CA1998",
"price": 1780,
"tickets": 5
});
6.5.3.3 使用jQuery实现JSONP调用
客户端代码:
jQuery(document).ready(function(){
$.ajax({
type: "get",
async: false,
url: "http://remoteserver.com/remote.aspx?code=CA1998",
dataType: "jsonp",
jsonp: "callback",//传递给请求处理程序或页面的,用以获得jsonp回调函数名的参数名(一般默认为:callback)
jsonpCallback:"flightHandler",//自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名,也可以写"?",jQuery会自动为你处理数据
success: function(json){
alert('票价 ' + data.price + ' 元');
},
error: function(){
alert('fail');
}
});
});
6.5.4 CORS
CORS的全称是“跨域资源共享”,它提出一种方法,允许JavaScript代码向另一个域名发出XMLHttpRequests请求,从而克服了同域限制。
CORS机制与JSONP模式的使用目的相同,而且更强大。JSONP只支持GET请求,CORS可以支持所有类型的HTTP请求。
JSONP的优势在于可以用于老式浏览器,以及可以向不支持CORS的网站请求数据。
6.5.5 Fetch API
Fetch API是一种新兴的规范,用来操作浏览器发出的网络请求,目的是在将来取代XMLHttpRequest。
6.6 window.postMessage方法
window.postMessage方法就是用来在某种程度上,绕过同域限制,实现不同域名的窗口(包括iframe窗口)之间的通信。
6.7 Web Storage:浏览器端数据储存机制
这个API用于在浏览器端储存数据。它分成两类:sessionStorage和localStorage。
它们很像cookie机制的强化版,能够动用大得多的存储空间(Chrome是2.5MB)。另外,与cookie一样,它们也受同域限制。
sessionStorage保存的数据,当会话结束时会被清空;
localStorage保存的数据长期存在。
除了保存期限的长短不同,这两个对象的属性和方法完全一样。
6.8 IndexedDB:浏览器端数据库
通俗地说,IndexedDB就是浏览器端数据库。
IndexedDB不属于关系型数据库(不支持SQL),更接近NoSQL数据库。
IndexedDB的下特点:
1、键值对储存。
2、异步。 IndexedDB操作时不会锁死浏览器。
3、支持事务。IndexedDB支持事务。
4、同域限制 每个数据库对应创建该数据库的域名。
5、储存空间大 一般来说不少于250MB。
6、支持二进制储存。
6.9 Web Notification API
Notification API是浏览器的通知接口,用于在用户的桌面显示通知信息。
具体的实现形式由浏览器自行部署,对于手机来说,一般显示在顶部的通知栏。
6.10 Performance API
Performance API用于精确度量、控制、增强浏览器的性能表现。
6.11 移动设备API
HTML 5推出了一系列针对移动设备的API。
比如获取显示区域、地理信息、震动手机、屏幕亮度、手机摆放方向等。
6.12 WebRTC
WebRTC是“网络实时通信”(Web Real Time Communication)的缩写。它最初是为了解决浏览器上视频通话而提出的,即两个浏览器之间直接进行视频和音频的通信,不经过服务器。后来发展到除了音频和视频,还可以传输文字和其他数据。