本章內(nèi)容
- 理解
window
對象--BOM 的核心 - 控制窗口,框架和彈出窗口
- 利用
location
對象中的頁面信息 - 使用
navigator
對象了解瀏覽器
8.1 window 對象
BOM
的核心對象是window
则涯,它表示瀏覽器的一個實例瓦戚。在瀏覽器中一也,window
對象有雙重角色获洲,它既是通過JavaScript
訪問瀏覽器窗口的一個接口擒滑,又是 ECMAScript 規(guī)定的Global
對象情萤。這意味著在網(wǎng)頁中定義的任何一個對象帆精,變量和函數(shù)较屿,都以window
作為其Global
對象,因此有權(quán)訪問parseInt()
等方法卓练。
8.1.1 全局作用域
所有在全局作用域中聲明的變量隘蝎,函數(shù)都會變成window
對象的屬性和方法。
拋開全局變量會成為window
對象的屬性不談襟企,定義全局變量與在window
對象上直接定義屬性還是有一點差別:全局變量不能通過delete
操作符刪除嘱么,而直接在window
對象上的定義的屬性可以。
另外顽悼,還要記住一件事:嘗試訪問未聲明的變量會拋出錯誤曼振,但是通過查詢window
對象,可以知道某個可能未聲明的變量是否存在蔚龙。
//這里會拋出錯誤冰评,因為`oldValue`未定義
var newValue = oldValue;
//這里不會拋出錯誤,因為這是一次屬性查詢
//newValue 的值是 undefined
var newValue = window.oldValue;
8.1.2 窗口關(guān)系及框架
如果頁面中包含框架木羹,則每個框架都有自己的 window
對象甲雅,并且保存在frames
集合中。在frames
集合中坑填,可以通過數(shù)值索引或者框架名稱來訪問相應(yīng)的window
對象抛人。每個window
對象都有一個name
屬性,其中包含框架的名稱脐瑰。
top
對象始終指向最高(最外)層的框架函匕。也就是瀏覽器窗口。使用它可以確保在一個框架中正確地訪問另一個框架蚪黑。因為對于在一個框架中編寫的任何代碼來說盅惜,其中的window
對象指向的都是那個框架的特定實例,而非最高層的框架忌穿。
8.1.3 窗口位置
var leftPos = (typeof window.screenLeft == "number") ? window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ? window.screenTop : window.screenY;
8.1.4 窗口大小
outerWidth
和outerHeight
返回瀏覽器窗口本身的尺寸抒寂;而innerWidth
和innerHeight
則表示該容器中頁面視圖區(qū)的大小(減去邊框?qū)挾龋?br>
document.documentElement.clientWidth
和document.documentElement.clientHeight
;document.body.clientWidth
和document.body.clientHeight
掠剑。
8.1.5 導(dǎo)航和打開窗口
使用window.open()
方法既可以導(dǎo)航到一個特定的 URL屈芜,也可以打開一個新的瀏覽器窗口。這個方法可以接收 4 個參數(shù):要加載的 URL朴译、窗口目標井佑、一個特性字符串以及一個表示新頁面是否取代瀏覽器歷史紀錄中當前加載頁面的布爾值。通常只需傳遞第一個參數(shù)眠寿,最后一個參數(shù)只在不打開新窗口的情況下使用躬翁。
如果傳遞了第二個參數(shù),而且該參數(shù)是已有窗口或框架的名稱盯拱,那么就會在具有該名稱的窗口或框架中加載第一個參數(shù)指定的 URL盒发。
//等同于<a target="topFrame"></a>
window.open("http://www.wrox.com/", "topFrame");
如果名叫 "topFrame" 的窗口或者框架,就會在該窗口或框架加載這個 URL狡逢;否則宁舰,就會創(chuàng)建一個新窗口并將其命名為 "topFrame"。此外奢浑,第二個參數(shù)也可以是下列任何一個特殊的窗口名稱: _self蛮艰、_parent、_top 或 _blank雀彼。
- 彈出窗口
如果第二個參數(shù)并不是已存在的窗口或框架壤蚜,那么該方法就會根據(jù)在第三個參數(shù)位置上傳入的字符串創(chuàng)建一個新窗口或新標簽頁。如果沒有傳入第三個參數(shù)详羡,那么就會打開一個帶有全部默認設(shè)置的新瀏覽器窗口仍律。在不打開新窗口的情況下,會忽略第三個參數(shù)实柠。
第三個參數(shù)是一個逗號分隔的設(shè)置字符串水泉,表示在新窗口中都顯示那些特性。
window.open("http://www.wrox.com/","wroxWindow", "height=400,width=400,top=0,left=10,resizable=yes");
window.open()
方法會返回一個指向新窗口的引用窒盐。引用的對象與其他window
對象大致相似草则,但可以對其進行更多控制。
var wroxWin = window.open("http://wrox.com/","wroxWindow");
wroxWin.resizeTo(500,500);
wroxWin.moveTo(100,100);
wroxWin.close();
- 安全機制
- 彈出窗口屏蔽程序
var wrox = window.open("http://www.wrox.com", "_blank");
if(wroxWin == null) {
alert("The popup was blocked!");
}
如果是瀏覽器擴展或其他程序阻止的彈出窗口蟹漓,那么window.open()
通常會拋出一個錯誤炕横。
var blocked = false;
try {
var wrox = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null) {
blocked = true;
}
}catch (ex) {
blocked = true;
}
if (blocked) {
alert("The popup was blocked!");
}
8.1.6 間歇調(diào)用和超時調(diào)用
超時調(diào)用需要使用window
對象的setTimeout()
方法,它接受兩個參數(shù):要執(zhí)行的代碼和以毫秒表示的時間(即在執(zhí)行代碼前需要等待多少毫秒)葡粒。其中份殿,第一個參數(shù)可以是一個包含 JavaScript 代碼的字符串膜钓,也可以是一個函數(shù)。
//不推薦傳遞字符串
setTimeout("alert("Hello world!")", 1000);
//推薦的調(diào)用方式
setTimeout(function(){alert("hello world!")}, 1000);
第二個參數(shù)告訴 JavaScript 再過多長時間把當前任務(wù)添加到隊列中卿嘲。如果隊列是空的颂斜,那么添加的代碼會立即執(zhí)行,否則拾枣,得等前面的代碼執(zhí)行完畢之后在執(zhí)行沃疮。
調(diào)用 setTimeout()
之后,該方法會返回一個數(shù)值 ID梅肤,表示超時調(diào)用司蔬。這個超時調(diào)用 ID 是計劃執(zhí)行代碼的唯一標識符,可以通過它來取消超時調(diào)用姨蝴。
var timeoutId = setTimeout(function () {alert("hello world!");}, 1000);
//
clearTimeout(timeoutId);
間歇調(diào)用與超時調(diào)用類似俊啼,只不過它會按照指定的時間間隔重復(fù)執(zhí)行代碼,直至間歇調(diào)用被取消或者頁面被卸載似扔。
setInterval(function(){alert("hello world!");}, 1000);
var intervalId = ...
clearInterval(intervalId);
使用超時調(diào)用來模擬間歇調(diào)用是一種最佳模式吨些,因為后一個間歇調(diào)用可能會在前一個間歇調(diào)用結(jié)束之前啟動。所以炒辉,最好不要使用間歇調(diào)用豪墅。
8.1.7 系統(tǒng)對話框
瀏覽器通過 alert()
、confirm()
和prompt()
方法可以調(diào)用系統(tǒng)對話框向用戶顯示消息黔寇。系統(tǒng)對話框與在瀏覽器中顯示的網(wǎng)頁沒有關(guān)系偶器,也不包含 HTML。它們的外觀由操作系統(tǒng)及(或)瀏覽器設(shè)置決定缝裤,而不是由 CSS 決定屏轰。此外,通過這幾個方法打開的對話框都是同步和模態(tài)的憋飞。也就是說霎苗,顯示這些對話框的時候代碼會停止執(zhí)行,而關(guān)掉這些對話框后代碼又會恢復(fù)執(zhí)行榛做。
為了確認用戶是單擊了 OK 還是 Cancel唁盏,可以檢查confirm()
方法返回的布爾值。
if (confirm("are you okay?")) {
alert("haha!");
} else {
alert("eee!");
}
prompt()
方法生成的是一個“提示”框检眯,用于提示用戶輸入一些文本厘擂。該方法接受兩個參數(shù):要顯示給用戶的文本提示和文本輸入域的默認值(可以是一個空字符串)。
如果用戶單擊了 OK 按鈕锰瘸,則prompt()
返回文本輸入框的值刽严;如果不是則返回null
。
8.2 location 對象
location
對象既是window
對象的屬性避凝,也是document
對象的屬性舞萄;換句話說眨补,window.location
和document.location
引用的是同一個對象。
8.2.1 查詢字符串參數(shù)
可以像下面這樣創(chuàng)建一個函數(shù)倒脓,用以解析查詢字符串渤涌,然后返回包含所有參數(shù)的一個對象:
function getQueryStringArgs () {
//取得查詢字符串并去掉開頭的問號
var qs = (location.search.length > 0 ? location.search.substring(1) : "");
//保存數(shù)據(jù)的對象
var args = {};
//取得每一項
var items = qs.lenth ? qs.split("&") : [];
var item = null;
var name = null;
var value = null;
var i = 0;
var len = items.length;
for (i = 0; i < len; i++) {
item = items[i].split("=");
name = decodeURIComponent(item[0]);
value = decodeURIComponent(item[1]);
if (name.length) {
args[name] = value;
}
}
return args;
}
8.2.2 位置操作
location.assign("http://www.wrox.com");
location.;
...
使用replace()
方法后,用戶不能回到前一個頁面把还。
location.reload(); //重新加載(有可能從緩存中加載)
location.reload(true); //重新加載(從服務(wù)器中加載)
最好將reload
放在代碼的最后一行。
8.3 navigator 對象
現(xiàn)已成為識別客戶端瀏覽器的事實標準茸俭。
8.3.1 檢測插件
對于非 IE 瀏覽器吊履,可以使用plugins
數(shù)組來達到這個目的。該數(shù)組中的每一項都包含下列屬性调鬓。
- name: 插件的名字艇炎。
- description: 插件的描述。
- filename: 插件的文件名腾窝。
- length: 插件所處理的 MIME 類型數(shù)量缀踪。
檢測 IE 中的插件比較麻煩。在 IE 中檢測插件的唯一方式就是使用專有的ActiveXObject
類型虹脯,并嘗試創(chuàng)建一個特定插件的實例驴娃。要想檢查特定的插件,就必須知道其 COM 標識符循集。
function hasIEPlugin (name) {
try {
new ActiveXObject(name);
return true;
} catch (ex) {
return false;
}
}
//檢測 Flash
alert(hasIEPlugin("ShockwaveFlash.ShockwaveFlash"));
//檢測 QuickTime
alert(hasIEPlugin("QuickTime.QuickTime"));
//檢測所有瀏覽器中的 QuickTime
function hasQuickTime() {
var result = hasPlugin("QuickTime");
if(!result) {
result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
}
}
8.3.2 注冊處理程序
8.4 screen 對象
8.5 history 對象
history
是window
對象的屬性唇敞,因此每個瀏覽器窗口、每個標簽頁乃至每個框架咒彤,都有自己的history
對象與特定的window
對象關(guān)聯(lián)疆柔。
使用go()
方法可以在用戶的歷史紀錄中任意跳轉(zhuǎn),可以向后也可以向前镶柱。該方法接受一個參數(shù)旷档,表示向后或向前跳轉(zhuǎn)的頁面數(shù)的一個整數(shù)值。負數(shù)表示向后跳轉(zhuǎn)歇拆,正數(shù)相反鞋屈。
//后退一頁
history.go(-1);
//前進一頁
history.go(1);
//前進兩頁
history.go(2);
也可以給go()
方法傳遞一個字符串參數(shù),此時瀏覽器會跳轉(zhuǎn)到歷史紀錄中包含該字符串的第一個位置---可能后退查吊,也可能前進谐区。如果歷史紀錄中不包含該字符串,那么這個方法什么也不做逻卖。
//跳轉(zhuǎn)到最近的 wrox.com 頁面
history.go("wrox.com");
//跳轉(zhuǎn)到最近的 nczonline.net 頁面
history.go("nczonline.net");
還可以使用back()
和forward()
來代替go()
宋列。
//后退一頁
history.back();
//前進一頁
history.forward();
還有一個length
屬性,保存著歷史紀錄的數(shù)量评也。
if (history.length == 0) {
//這應(yīng)該是用戶打開窗口的第一個頁面
}
8.6 小結(jié)
瀏覽器對象模型以window
對象為依托炼杖,表示瀏覽器窗口以及頁面可見區(qū)域灭返。同時,window
對象還是 ECMAScript 中的Global
對象坤邪,因而所有全局變量和函數(shù)都是它的屬性熙含,且所有原生的構(gòu)造函數(shù)及其他函數(shù)也都存在與它的命名空間下。
- 在使用框架時艇纺,每個框架都有自己的
window
對象以及所有原生構(gòu)造函數(shù)及其他函數(shù)的副本怎静。每個框架都保存在frames
集合中,可以通過位置或通過名稱來訪問黔衡。 - 有一些窗口指針蚓聘,可以用來引用其他框架,包括父框架盟劫。
-
top
對象始終指向最外圍的框架夜牡,也就是整個瀏覽器窗口。 -
parent
對象表示包含當前框架的框架侣签,而self
對象則回指window
塘装。 - 使用
location
對象可以通過編程方式來訪問瀏覽器的導(dǎo)航系統(tǒng)。設(shè)置相應(yīng)的屬性影所,可以逐段或整體性地修改瀏覽器的 URL蹦肴。 - 調(diào)用
replace()
方法可以導(dǎo)航到一個新 URL,同時 URL 會替換瀏覽器歷史紀錄中當前顯示的頁面型檀。 -
navigator
對象提供了與瀏覽器有關(guān)的信息冗尤。到底提供哪些信息,很大程度上取決于用戶的瀏覽器胀溺;不過裂七,也有一些公共的屬性存在于所有瀏覽器中。