## BOM
Window對象是客戶端JavaScript程序的全局對象。
**11.1 計時器**
`setTimeout()`和`setInterval()`可以用來注冊在指定的時間之后單次或重復調用的函數。兩者都是客戶端JavaScript中的全局函數,也就是Window對象的方法。
**(1)setTimeout()**
`setTimeout()`方法用來實現一個函數在指定的毫秒數之后運行,返回一個值,這個值可以傳遞給clearTimeout()用于取消這個函數的執行。
```
var times = setTimeout(function(){},1000); //1000毫秒后執行
clearTimeout(times); //取消執行
```
**(2)setInterval()**
setInterval()方法和setTimeout()一樣,只不過這個函數會在指定毫秒數的間隔里重復調用,也返回一個值,這個值傳遞給clearInterval(),用于取消后續函數的調用。
```
var times = setInterval(function(){},1000); //每隔1000毫秒調用一次function
clearInterval(times); //取消后續函數執行
```
注意:如果以0毫秒的超時時間來調用setTimeout(),那么指定的函數不會立刻執行。相反,會把它放到隊列中,等到前面處于等待狀態的事件處理程序全部執行完成后,再“立即”調用它。
**11.2 瀏覽器定位和導航**
Window對象的`location`屬性引用的是`Location`對象,它表示該窗口中當前顯示的文檔的URL,并定義了方法來使窗口載入新的文檔。
Document對象的location屬性也引用到Location對象:
```
window.location === document.location //總是返回true
```
Document對象也有一個URL屬性,是文檔首次載入后保存該文檔的URL的靜態字符串。如果定位到文檔中的片斷標識符(如#top),Location對象會做相應的更新,而document.URL屬性卻不會改變。
**11.2.1 解析URL**
Location對象href屬性是一個字符串,href屬性包含ULR的完整文本。Location對象的toString()方法返回href屬性的值,因此在會隱式調用toString()的情況下,可以用location代替location.href。
```
// 當前網址為 http://user:passwd@www.example.com:4097/path/a.html?x=111#part1location.href // "http://user:passwd@www.example.com:4097/path/a.html?x=111#part1"
location.protocol // "http:"
location.host // "www.example.com:4097"
location.hostname // "www.example.com"
location.port // "4097"
location.pathname // "/path/a.html"
location.search // "?x=111"
location.hash // "#part1"
location.user // "user"
location.password // "passed"
```
protocol、host、hostname、port、pathname和search屬性是“URL分解”屬性,是可寫的,對它們重新賦值的話,會改變URL的位置,并且瀏覽器會載入一個新的文檔。
`Location`對象的方法:
- `location.assign()`:使窗口載入并顯示指定的URL中的文檔。
- `location.replace()`:和assign()方法類似,但它在載入新文檔之前會從瀏覽歷史中把當前文檔刪除。這樣“后退”按鈕就不會把瀏覽器帶回到原始文檔。
- `location.reload()`:重新載入當前文檔,可傳入一個布爾值為參數,默認false。如果為true,則優先從服務器重新加載;否則優先從本地緩存中重新加載。
當然,我們還有更直接跳轉到新頁面的方法:
```
location = 'http://baidu.com';
//或者
location.href = 'http://baidu.com';
```
純粹的片斷標識符是相對URL的一種類型,它不會讓瀏覽器載入新文檔,而是使瀏覽器滾動到文檔的某個位置。
注意:#top標識符是個特殊值:如果文檔中沒有元素的ID是“top”,它會讓瀏覽器滾動到文檔開始處。
```
location = '#top'; //跳轉到文檔的頂部
```
**11.3 瀏覽歷史**
Window對象的history屬性引用的是該窗口的History對象。History對象是用來把窗口瀏覽歷史用文檔和文檔狀態列表的形式表示。
History對象的length屬性表示瀏覽歷史表中的元素數量。比如你在當前窗口訪問了三個不同的網址,那么history.length就等于3。
History對象還提供了一系列的方法,讓我們在歷史記錄中自由前進和后退。
- back():移動到上一個訪問頁面,等同于瀏覽器的后退鍵。
- forward():移動到下一個訪問頁面,等同于瀏覽器的前進鍵。
- go():接受一個整數作為參數,移動到該整數指定的頁面,比如go(1)相當于forward(),go(-1)相當于back()。
如果移動的位置超出了訪問歷史的邊界,以上三個方法并不報錯,而是默默的失敗。
history.go(0)相當于刷新當前頁面。
```
history.go(0)
```
注意:如果窗口包含多個子窗口(比如<iframe>元素),子窗口的瀏覽歷史會按時間順序穿插到主窗口的歷史中。這就是意味著主窗口調用back()可能會導致其中一個子窗口往回跳轉到前一個顯示的文檔,而主窗口保留當前狀態不變。
HTML5為history對象添加了兩個新方法,用來添加和修改歷史記錄條目。
- `history.pushState()`:會改變referrer的值,而在你調用方法后創建的 XMLHttpRequest 對象會在 HTTP 請求頭中使用這個值。referrer的值則是創建 XMLHttpRequest 對象時所處的窗口的URL。
- `history.replaceState()`:會修改當前歷史記錄條目而并非創建新的條目
**(1)history.pushState()**
history.pushState方法接受三個參數,依次為:
state:一個與指定網址相關的狀態對象,popstate事件觸發時,該對象會傳入回調函數。如果不需要這個對象,此處可以填null。
title:新頁面的標題,但是所有瀏覽器目前都忽略這個值,因此這里可以填null。
url:新的網址,必須與當前頁面處在同一個域。瀏覽器的地址欄將顯示這個網址。
```
假定當前網址是example.com/1.html,我們使用pushState方法在瀏覽記錄(history對象)中添加一個新記錄。
var stateObj = { foo: 'bar' };
history.pushState(stateObj, 'page 2', '2.html');
```
添加上面這個新記錄后,瀏覽器地址欄立刻顯示`example.com/2.html`,但并不會跳轉到2.html,甚至也不會檢查2.html是否存在,它只是成為瀏覽歷史中的最新記錄。假定這時你訪問了google.com,然后點擊了倒退按鈕,頁面的url將顯示2.html,但是內容還是原來的1.html。你再點擊一次倒退按鈕,url將顯示1.html,內容不變。
總之,pushState方法不會觸發頁面刷新,只是導致history對象發生變化,地址欄會有反應。
如果pushState的url參數,設置了一個新的錨點值(即hash),并不會觸發hashchange事件。如果設置了一個跨域網址,則會報錯。
**(2)history.replaceState()**
history.replaceState方法的參數與pushState方法一模一樣,區別是它修改瀏覽歷史中當前紀錄。
假定當前網頁是`example.com/example.html`。
```
history.pushState({page: 1}, 'title 1', '?page=1');
history.pushState({page: 2}, 'title 2', '?page=2');
history.replaceState({page: 3}, 'title 3', '?page=3');
history.back()
// url顯示為http://example.com/example.html?page=1
history.back()
// url顯示為http://example.com/example.html
history.go(2)
// url顯示為http://example.com/example.html?page=3
```
**(3)history.state屬性**
`history.state`屬性返回當前頁面的state對象。
```
history.pushState({page: 1}, 'title 1', '?page=1');
history.state // { page: 1 }
```
**(4)popstate事件**
每當同一個文檔的瀏覽歷史(即history對象)出現變化時,就會觸發popstate事件。
需要注意的是,僅僅調用pushState方法或replaceState方法 ,并不會觸發該事件,只有用戶點擊瀏覽器倒退按鈕和前進按鈕,或者使用JavaScript調用back、forward、go方法時才會觸發。另外,該事件只針對同一個文檔,如果瀏覽歷史的切換,導致加載不同的文檔,該事件也不會觸發。
使用的時候,可以為popstate事件指定回調函數。這個回調函數的參數是一個event事件對象,它的state屬性指向pushState和replaceState方法為當前URL所提供的狀態對象(即這兩個方法的第一個參數)。
```
window.onpopstate = function (event) {
console.log('location: ' + document.location);
console.log('state: ' + JSON.stringify(event.state));
};
// 或者
window.addEventListener('popstate', function(event) {
console.log('location: ' + document.location);
console.log('state: ' + JSON.stringify(event.state));
});
```
上面代碼中的event.state,就是通過pushState和replaceState方法,為當前URL綁定的state對象。
這個state對象也可以直接通過history對象讀取。
var currentState = history.state;
注意:頁面第一次加載的時候,在load事件發生后,Chrome和Safari瀏覽器(Webkit核心)會觸發popstate事件,而Firefox和IE瀏覽器不會。
**11.4 瀏覽器和屏幕信息**
Window對象的navigator和screen屬性,分別引用的是Navigator和Screen對象。
**11.4.1 Navigator對象**
Window對象的navigator屬性引用的是包含瀏覽器產商和版本信息的Navigator對象。
**Navigator對象的屬性**
**(1)navigator.appName、navigator.appVersion**
appName是Web瀏覽器的全稱。在IE中,是“Microsoft Internet Explorer”。在其他瀏覽器中,是“Netscape”。
appVersion此屬性通常以數字開始,并跟著包含瀏覽器產商和版本信息的詳細字符串。字符串前面的數字通常是4.0或5.0,表示它是第4或第5代兼容的瀏覽器。
**(2)navigator.userAgent**
navigator.userAgent屬性返回瀏覽器的User-Agent字符串,標示瀏覽器的廠商和版本信息。它包含了appVersion中的所有信息。
下面是Chrome瀏覽器的userAgent。
```
navigator.userAgent
//Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36
```
利用這個屬性,我們還可以判斷手機瀏覽器的類型。
```
if (/AppleWebKit.*Mobile/i.test(navigator.userAgent) || (/MIDP|SymbianOS|NOKIA|SAMSUNG|LG|NEC|TCL|Alcatel|BIRD|DBTEL|Dopod|PHILIPS|HAIER|LENOVO|MOT-|Nokia|SonyEricsson|SIE-|Amoi|ZTE/.test(navigator.userAgent))) {
try {
if (/Android|Windows Phone|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) {
//手機瀏覽器
} else if (/iPad/i.test(navigator.userAgent)) {
//ipad
} else {}
} catch (e) {}
} else {
//非手機瀏覽器
}
```
如果你只是簡單的判斷是否手機瀏覽器。
```
var ua = navigator.userAgent.toLowerCase();
if(/mobi/i.test(ua)){
//手機瀏覽器
}else{
//非手機瀏覽器
}
```
**(3)navigator.platform**
返回用戶的操作系統信息
比如我的:
```
navigator.platform
//win32
```
**(4)navigator.onLine**
表示瀏覽器當前是否連接到網絡。返回一個布爾值。
**(5)navigator.geolocation**
返回一個Geolocation對象,包含用戶地理位置信息。詳情請看《HTML5 API》
**(6)navigator.javaEnabled()**
javaEnabled方法返回一個布爾值,表示瀏覽器是否能運行Java Applet小程序。
**(7)navigator.cookieEnable()**
cookieEnabled方法返回一個布爾值,表示瀏覽器是否能儲存Cookie。
**11.4.2 Screen對象**
Window對象的screen屬性引用的是Screen對象,它提供有關窗口顯示的大小和可用的顏色數量的信息。
**(1)screen.width、screen.height**
screen.width和screen.height分別返回以像素為單位的窗口大小(設備的寬高)。
**(2)screen.availHeight、screen.availWidth**
screen.availHeight和screen.availWidth屬性返回屏幕可用的高度和寬度,單位為像素。它們的值為屏幕的實際大小減去操作系統某些功能占據的空間,比如系統的任務欄。
**(3)screen.colorDepth**
screen.colorDepth屬性返回屏幕的顏色深度,一般為16(表示16-bit)或24(表示24-bit)。
**11.5 對話框**
Window對象提供了3個方法來向用戶顯示簡單的對話框。
- `alert()`:向用戶顯示一條消息并等待用戶關閉對話框。
- `confirm()`:同樣顯示一條消息,要求用戶單擊“確認”或“取消”按鈕,并返回一個布爾值。
- `prompt()`:同樣顯示一條消息,等待用戶輸入字符串,并返回這個字符串。
這三個方法都具有堵塞效應,一旦彈出對話框,整個頁面就是暫停執行,等待用戶做出反應。
**(1)alert()**
```
alert(1);
```
**(2)confirm()**
```
var c = confirm('確認登錄');
```
confirm的一個用途是,當用戶離開當前頁面時,彈出一個對話框,詢問用戶是否真的離開。
```
window.onunload = function() {
return confirm('你確定要離開當面頁面嗎?');
}
```
**(3)prompt()**
```
// 格式
var result = prompt(text[, default]);
//實例
var result = prompt('您的年齡?',18);
```
prompt方法的返回值是一個字符串(有可能為空)或者null,具體分成三種情況。
用戶輸入信息,并點擊“確定”,則用戶輸入的信息就是返回值。
用戶沒有輸入信息,直接點擊“確定”,則輸入框的默認值就是返回值。
用戶點擊了“取消”(或者按了Esc按鈕),則返回值是null。
注意:這些對話框中顯示的文本是純文本,而不是HTML格式的文本。只能使用空格、換行符或各種標點符號來格式化這些對話框。
**11.6 錯誤處理**
Window對象的onerror屬性是一個事件處理程序,當未捕獲的異常傳播到調用棧上時就會調用它,并把錯誤信息輸出到瀏覽器的JavaScript控制臺上。
```
window.onerror = function (message, filename, lineno, colno, error) {
console.log("出錯了!--> %s", error.stack);
};
```
五個參數的含義:
```
message:出錯信息
filename:出錯腳本的網址
lineno:行號
colno:列號
error:錯誤對象
```
老式瀏覽器只支持前三個參數。
并不是所有的錯誤,都會觸發JavaScript的error事件(即讓JavaScript報錯),只限于以下三類事件。
- JavaScript語言錯誤
- JavaScript腳本文件不存在
- 圖像文件不存在
以下兩類事件不會觸發JavaScript的error事件。
- CSS文件不存在
- iframe文件不存在
注意:onerror處理程序的返回值也很重要。如果onerror處理程序返回false,它通知瀏覽器事件處理程序已經處理了錯誤,不需要其他操作。也就是說,瀏覽器不應該顯示它自己的錯誤信息。遺憾的是,由于歷史原因,Firefox里的錯誤處理程序必須返回true來表示它已經處理了錯誤。
**11.7 多窗口和窗體**
由于網頁可以使用`<iframe>`嵌套多個網頁,因此一個網頁之中會形成多個窗口。另一情況是,子網頁之中又嵌入別的網頁,形成多級窗口。每個窗口的Window對象都是獨立的,互不干擾。
瀏覽器提供了一些特殊變量,用來返回其他窗口。
```
top:頂層窗口,即最上層的那個窗口
parent:父窗口
self:當前窗口,即自身
下面的代碼可以判斷當前窗口是否是頂層窗口
window.top === window.self
與這些變量對應,瀏覽器還提供一些特殊的窗口名,供open方法、`<a>`標簽、`<form>`標簽等引用。
_top:頂層窗口
_parent:父窗口
_blank:新窗口
```
**11.7.1 打開和關閉窗口**
使用Window對象的open()方法可以打開一個新的瀏覽器窗口。Window.open()載入指定的URL到新的或已存在的窗口中,并返回代表那個窗口的Window對象。
open方法一共可以接受四個參數。
第一個參數:字符串,表示新窗口的網址。如果省略,默認網址就是`about:blank`。
第二個參數:字符串,表示新窗口的名字。如果該名字的窗口已經存在,則跳到該窗口,不再新建窗口。如果省略,就默認使用_blank,表示新建一個沒有名字的窗口。
第三個參數:字符串,內容為逗號分隔的鍵值對,表示新窗口的參數,比如有沒有提示欄、工具條等等。如果省略,則默認打開一個完整UI的新窗口。
第四個參數:布爾值,表示第一個參數指定的網址,是否應該替換history對象之中的當前網址記錄,默認值為false。顯然,這個參數只有在第二個參數指向已經存在的窗口時,才有意義。
```
var modal = window.open(
'example.html',
'modalWindow',
'height=200,width=300'
);
modal.window.name //modalWindow
```
window.close方法用于關閉當前窗口,一般用來關閉window.open方法新建的窗口。
modal.close();
該方法只對頂層窗口有效,iframe框架之中的窗口使用該方法無效。
**11.7.2 窗體**
窗體是通過`<iframe>`元素創建的,我們可以像獲取其他元素一樣,獲取一個表示`<iframe>`的元素對象,同時,`<iframe>`元素有`contentWindow`屬性,引用該窗體的Window對象。
```
<iframe id='f'></iframe>
var f = document.getElementById('f');
var win = f.contentWindow; //子窗體的Window對象
var doc = f.contentDocument; //等同于f.contentWindow.document
//獲取子窗體的變量和屬性
f.funciton()
f.title
```
iframe嵌入窗口的window對象,有一個frameElement屬性,返回它在父窗口中的DOM節點。對于頂級窗口,該屬性等于null。
```
win.frameElement === f //true
window.frameElement === null //true
```
當然,也可以使用Window對象的frames屬性,它引用自身包含的窗口或窗體的子窗體。返回一個類數組對象。
var f = window.iframes[0];
注意:frames[]數組里的元素是Window對象,而非`<iframe>`元素。
利用這個屬性,實現窗口之間的互相引用。比如,frames[0]返回第一個子窗口,frames[1].frames[2]返回第二個子窗口內部的第三個子窗口,parent.frames[1]返回父窗口的第二個子窗口。
如果`<iframe>`元素設置了name或id屬性,那么屬性值會自動成為(Window對象的屬性)全局變量,并且可以通過window.frames屬性引用,返回子窗口的window對象。
```
// HTML代碼為<iframe id="myFrame">
myFrame // [HTMLIFrameElement]
frames.myframe === myFrame // true
```
另外,name屬性的值會自動成為子窗口的名稱,可以用在window.open方法的第二個參數,或者`<a>`和`<frame>`標簽的target屬性。
- 前言
- JavaScript簡介
- 基本概念
- 語法
- 數據類型
- 運算符
- 表達式
- 語句
- 對象
- 數組
- 函數
- 引用類型(對象)
- Object對象
- Array對象
- Date對象
- RegExp對象
- 基本包裝類型(Boolean、Number、String)
- 單體內置對象(Global、Math)
- console對象
- DOM
- DOM-屬性和CSS
- BOM
- Event 事件
- 正則表達式
- JSON
- AJAX
- 表單和富文本編輯器
- 表單
- 富文本編輯器
- canvas
- 離線應用
- 客戶端存儲(Cookie、Storage、IndexedDB)
- HTML5 API
- Video/Audio
- Geolocation API
- requestAnimationFrame
- File API
- FullScreen API
- IndexedDB
- 檢測設備方向
- Blob
- vibrate
- Luminosity API
- WebRTC
- Page Visibility API
- Performance API
- Web Speech
- Notification
- 面向對象的程序設計
- 概述
- this關鍵字
- 原型鏈
- 作用域
- 常用API合集
- SVG
- 錯誤處理機制
- JavaScript開發技巧合集
- 編程風格
- 垃圾回收機制