RYF javascript笔记5


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 网页底部加载

网页加载流程是这样的:

  1. 浏览器开始解析HTML网页
  2. 解析过程中,发现script标签
  3. 暂停解析,下载script标签中的外部脚本
  4. 下载完成,执行脚本
  5. 恢复往下解析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)的缩写。它最初是为了解决浏览器上视频通话而提出的,即两个浏览器之间直接进行视频和音频的通信,不经过服务器。后来发展到除了音频和视频,还可以传输文字和其他数据。

推荐阅读更多精彩内容