<h1 id="8">第8章 BOM</h1>
本章內(nèi)容主要是
- 理解window對(duì)象
- 控制窗口肤晓、框架和彈出窗口
- 利用location對(duì)象中的頁面信息
- 使用navigator對(duì)象了解瀏覽器
<h2 id="8.1">8.1 window對(duì)象</h2>
- BOM的核心對(duì)象是window抹凳,它表示瀏覽器的一個(gè)實(shí)例油狂。
- window對(duì)象既是通過JS訪問瀏覽器窗口的一個(gè)接口损晤,又是ES規(guī)定的Global對(duì)象
- 網(wǎng)頁中定義的熱呢一個(gè)對(duì)象灸促、變量和函數(shù)瓦侮,都以window作為其Global對(duì)象
<h3 id="8.1.1">8.1.1 全局作用域</h3>
所有在全局作用域中聲明的變量、函數(shù)都會(huì)變成window對(duì)象的屬性和方法
定義全局變量和直接在window對(duì)象上定義屬性有一點(diǎn)差別:全局變量不能通過delete操作符刪除意述,而直接在window對(duì)象上定義的屬性可以提佣。這是因?yàn)槭褂胿ar語句添加的window屬性有一個(gè)名為[[Configurable]]的特性,值被設(shè)為false
-
嘗試訪問未聲明的變量會(huì)拋出錯(cuò)誤荤崇,但是通過查詢window對(duì)象拌屏,可以知道某個(gè)可能未聲明的變量是否存在
//這樣不會(huì)有錯(cuò)誤。值是undefined var newValue = window.oldValue; //拋出錯(cuò)誤 var newValue = oldValue;
<h3 id="8.1.2">8.1.2 窗口關(guān)系及框架</h3>
- 如果頁面中包含框架(像frameset這種)术荤,則每個(gè)框架都有自己的window對(duì)象倚喂,并且保存在frames集合中。
- 在frames集合中喜每,可以通過數(shù)值索引(0開始务唐,從左到右,從上到下)或者框架名稱來訪問相應(yīng)的window對(duì)象
- 每個(gè)window對(duì)象都有一個(gè)name屬性带兜,其中包含框架的名稱
top對(duì)象:
- top對(duì)象始終指向最高(最外)層的框架枫笛,也就是瀏覽器窗口,使用它可以確保在一個(gè)框架中正確地訪問另一個(gè)框架
window對(duì)象:
- 在一個(gè)框架中的window指向的都是自己那個(gè)框架刚照,不是最高層的
parent對(duì)象:
- 始終指向當(dāng)前框架的直接上層框架
- 在某些情況下刑巧,parent有可能等于top;在沒有框架的情況下,parent一定等于top(都是window)
self對(duì)象:
- 始終指向window
- 引入self只是為了與top和parent對(duì)應(yīng)起來
<h3 id="8.1.3">8.1.3 窗口關(guān)系及框架</h3>
跨瀏覽器取得窗口左邊和上邊的位置:
var leftPos = (typeof window.screenLeft == "number")?
window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number")?
window.scrrenTop : window.screenY;
這是因?yàn)镾afari啊楚、Opera和Chrome中存在screenLeft和screenTop屬性吠冤,而在Firefox中是scrrenX和ScreenY
無法在跨瀏覽器的條件下取得窗口左邊和上邊的精確坐標(biāo)值,因?yàn)樵贔irefox和Safari中返回的是整個(gè)瀏覽器窗口相對(duì)于屏幕的坐標(biāo)值恭理,在IE拯辙、Opera和Chrome中返回的是頁面可見區(qū)域(不包括工具欄)到屏幕左邊和上邊的值
將窗口精確地移動(dòng)到一個(gè)新位置的方法:
這兩種方法可能會(huì)被瀏覽器禁用。且不適用于框架颜价,只對(duì)最外層的window對(duì)象使用
-
moveTo()
- 參數(shù):新位置的x和y坐標(biāo)
-
moveBy()
- 參數(shù):在水平和垂直方向上移動(dòng)的像素?cái)?shù)
<h3 id="8.1.4">8.1.4 窗口大小</h3>
不同瀏覽器中返回的innerWidth涯保、innerHeight、outerWidth和outerHeight不一樣周伦,因此無法最終確定瀏覽器窗口本身的大小夕春,但可以取得頁面視口的大小
var pageWidth = wimdow.innerWidth,
pageHeight = window.innerHeight;
if(typeof pageWidth != "number"){
if(document.compatMode == "CSS1Compat"){//判斷是不是標(biāo)準(zhǔn)模式
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
}else{
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
調(diào)整瀏覽器窗口大小的兩個(gè)方法:
與移動(dòng)窗口位置的兩個(gè)方法類似,也有可能被瀏覽器禁用专挪。同樣不適用于框架及志,只能對(duì)最外層的window對(duì)象使用
-
resizeTo():
- 參數(shù):瀏覽器窗口的新寬度和新高度
-
resizeBy():
- 參數(shù):新窗口與原窗口的寬度和高度之差
<h3 id="8.1.5">8.1.5 導(dǎo)航和打開窗口</h3>
window.open():
-
參數(shù):要加載的URL、窗口目標(biāo)寨腔、一個(gè)特性字符串速侈、一個(gè)表示新頁面是否取代瀏覽器歷史記錄中當(dāng)前加載頁面的布爾值
第一個(gè)參數(shù):通常只需傳遞第一個(gè)參數(shù)。
-
第二個(gè)參數(shù):
-
該參數(shù)是已有窗口或框架的名稱
- 在指定的窗口或框架中加載指定URL
- 代碼:
//等同于<a target="topFrame"></a>
window.open("http://www.baidu.com/","topFrame");
- 如果沒有窗口或框架的名稱是topFrame脆侮,就會(huì)創(chuàng)建一個(gè)新窗口并將其命名為topFrame
_self
_parent
_top
_blank
-
-
第三個(gè)參數(shù):
如果第二個(gè)參數(shù)并不是已經(jīng)存在的窗口或框架锌畸,那么就會(huì)根據(jù)在第三個(gè)參數(shù)位置上傳入的字符串創(chuàng)建一個(gè)新窗口或新標(biāo)簽頁勇劣。如果沒有第三個(gè)參數(shù)靖避,就會(huì)打開一個(gè)帶有全部默認(rèn)設(shè)置的新瀏覽器窗口
在不打開新窗口的情況下,會(huì)忽略第三個(gè)參數(shù)
是一個(gè)用逗號(hào)分隔的設(shè)置字符串比默,表示新窗口的特性
-
整個(gè)特性字符串中不能有空格幻捏,比如:
window.open("http://www.baidu.com/","topFrame","height=400,width=400");
第四個(gè)參數(shù):只在不打開新窗口的情況下使用
-
返回:一個(gè)指向新窗口的引用
用途:可以針對(duì) 通過window.open()創(chuàng)建的窗口 調(diào)整大小或移動(dòng)位置
-
代碼:
var wroxWin = window.open("http://www.baidu.com/","wroxWindow","height=400,width=400"); wroxWin.resizeTo(500,500); wroxWin.moveTo(100,100)
wroxWin.close()
還可以關(guān)閉這個(gè)新打開的窗口要注意的是對(duì)于瀏覽器的主窗口,如果沒有得到用戶允許是不能關(guān)閉的(除了彈出窗口可以調(diào)用
top.close()
關(guān)閉)
-
opener屬性
- 定義于新窗口的最外層window對(duì)象(top)中命咐,指向原始窗口(調(diào)用
window.open()
的窗口或框架) - 當(dāng)把opener屬性設(shè)置為null時(shí)篡九,就是告訴瀏覽器新建的標(biāo)簽頁不需要與打開它的標(biāo)簽頁通信,因此可以在獨(dú)立的進(jìn)程中運(yùn)行醋奠。標(biāo)簽頁的聯(lián)系一旦切斷榛臼,將沒有辦法恢復(fù)
- 定義于新窗口的最外層window對(duì)象(top)中命咐,指向原始窗口(調(diào)用
彈出窗口屏蔽程序
內(nèi)置的屏蔽程序阻止彈出窗口:window.open()返回null
-
擴(kuò)展或其他程序阻止彈出窗口:拋出一個(gè)錯(cuò)誤
因此準(zhǔn)確檢測(cè)出彈出窗口是否被屏蔽的代碼如下:var blocked = false;
try {
var wroWin = window.open(http://www.baidu.com/","_blank");
if(wroWin == null){
blocked = true;
}
} catch (ex){
blocked = true;
}
if(blocked){
alert("The popup was blocked");
}
<h3 id="8.1.6">8.1.6 間歇調(diào)用和超時(shí)調(diào)用</h3>
JS是單線程語言,但它允許通過設(shè)置超時(shí)值和間歇時(shí)間值來調(diào)度代碼在特定的時(shí)刻執(zhí)行窜司。
-
超時(shí)調(diào)用:setTimeOut()
-
參數(shù):要執(zhí)行的代碼和以毫秒表示的時(shí)間
- 第一個(gè)參數(shù):可以是一個(gè)包含JS代碼的字符串(同eval()函數(shù)里的字符串)沛善,也可以是一個(gè)函數(shù)
- 不建議以字符串作為第一個(gè)參數(shù)。因?yàn)榭赡軐?dǎo)致性能缺失
- 第二個(gè)參數(shù):是一個(gè)表示等待多長(zhǎng)時(shí)間的毫秒數(shù)塞祈。JS是一個(gè)單線程的解釋器金刁,有一個(gè)JS任務(wù)隊(duì)列,這些任務(wù)按照將它們添加到隊(duì)列 的順序執(zhí)行。也就是說這個(gè)參數(shù)只是指定多長(zhǎng)時(shí)間后把任務(wù)添加到隊(duì)列尤蛮。但不一定會(huì)立即執(zhí)行(前面可能還有任務(wù))媳友。
-
返回:一個(gè)數(shù)值ID,表示超時(shí)調(diào)用
這個(gè)超時(shí)調(diào)用ID是計(jì)劃執(zhí)行代碼的唯一標(biāo)識(shí)符
-
只要指定的時(shí)間尚未過去产捞,就可以取消尚未執(zhí)行的超時(shí)調(diào)用計(jì)劃:傳入ID
clearTimeOut(timeoutId);
-
-
間歇調(diào)用:setInterval()
- 參數(shù):(與setTimeOut()相同)要執(zhí)行的代碼和以毫秒表示的時(shí)間
- 區(qū)別:按照指定的時(shí)間間隔重復(fù)執(zhí)行代碼醇锚,直到間歇調(diào)用被取消或者頁面被卸載
- 返回:間歇調(diào)用ID
- 取消:
clearInterval(Id)
一個(gè)常見的使用間歇調(diào)用的例子
var num =0;
var max = 10;
var intervalId = null;
function incrementNumber(){
num++;
//如果執(zhí)行次數(shù)達(dá)到max,則取消后續(xù)尚未執(zhí)行的調(diào)用
if(num == max){
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber,500);
與以上代碼相同功能的超時(shí)調(diào)用:
var num = 0;
var max = 10;
function incrementMunber(){
num++;
if(num < max){
setTimeout(incrementNumber,500);
}else{
alert("Done");
}
}
setTimeout(incrementNumber,500);
比較上面兩段代碼坯临,可以看出超時(shí)調(diào)用不需要跟蹤超時(shí)調(diào)用ID搂抒。一般認(rèn)為,使用超時(shí)調(diào)用模擬間歇調(diào)用是一種最佳模式尿扯。在開發(fā)環(huán)境下求晶,很少使用間歇調(diào)用,因?yàn)楹笠粋€(gè)間歇調(diào)用可能會(huì)在前一個(gè)間歇調(diào)用結(jié)束前啟動(dòng)衷笋。所以最好不要使用間歇調(diào)用
<h3 id="8.1.7">8.1.7 系統(tǒng)對(duì)話框</h3>
以下三個(gè)不涉及HTML芳杏、CSS、JS
- alert():警告
- confirm():確認(rèn)
- prompt():提示
- 參數(shù):要顯示給用戶的文本提示和文本輸入域(可以是"")
- 返回:?jiǎn)螕鬙K則返回文本輸入域的值辟宗,單擊cancel或通過其他方式關(guān)閉對(duì)話框則返回null
以下兩個(gè)可以通過JS打開的對(duì)話框:查找和打印爵赵。這兩個(gè)對(duì)話框都是異步顯示的,能夠?qū)⒖刂茩?quán)立即交還給腳本泊脐。與用戶通過瀏覽器菜單的查找和打印命令打開的對(duì)話框相同
- 打涌栈谩:
window.print();
- 查找:
window.find();
<h2 id="8.2">8.2 location對(duì)象</h2>
location提供了與當(dāng)前窗口中加載的文檔有關(guān)的信息,還提供了一些導(dǎo)航功能容客。
location既是window對(duì)象的屬性秕铛,也是document對(duì)象的屬性。
location將URL解析為獨(dú)立的片段
<h3 id="8.2.1">8.2.1 查詢字符串參數(shù)</h3>
以下函數(shù)解析查詢字符串缩挑,然后返回包含所有參數(shù)的一個(gè)對(duì)象:
function getQueryStringArgs(){
var qs = location.search.length > 0 ? location.search.substring(1) : "";
var args = {};
var items = qs.length > 0 ? qs.split("&") : [];
var item = null;
var name = null;
var value = null;
for(var i = 0; i<items.length; i++){
item = items[i].split("=");
name = decodeURIComponent(item[0]);
value = decodeURIComponent(item[1]);
if(name.length){
args[name] = value;
}
}
return args;
}
<h3 id="8.2.2">8.2.2 位置操作</h3>
以下三種方法本質(zhì)上都是調(diào)用assign()方法但两,location.href比較常用
location.assign(URL);
window.location = URL;
location.href = URL;
通過改變location對(duì)象的其他屬性值來改變當(dāng)前加載的頁面:
//假設(shè)初始URL為http://www.wrox.com/WileyCDA/
//http://www.wrox.com/WileyCDA/#section1
location.hash = "#section1";
//http://www.wrox.com/WileyCDA/?q=javascript
location.search = "?q=javascript";
//http://www.yahoo.com/WileyCDA/
location.hostname = "www.yahoo.com";
//http://www.wrox.com/mydir/
location.pathname = "mydir";
//http://www.wrox.com:8080/WileyCDA/
location.port = 8080;
每次修改location的屬性(除hash),頁面都會(huì)以新URL重新加載
replace()
方法:
作用:禁用后退按鈕
-
示例:訪問該網(wǎng)頁的時(shí)候1s后導(dǎo)航到百度供置,并且后退按鈕被禁用
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> </head> <body> <script type="text/javascript"> setTimeout(function () { location.replace("http://www.baidu.com/"); },1000); </script> </body> </html>
reload()
方法:
location.reload();//重新加載(有可能從緩存中加載)
location.reload(true);//重新加載(從服務(wù)器重新加載)
- 位于reload()之后的代碼可能不執(zhí)行谨湘,取決于網(wǎng)絡(luò)延遲或系統(tǒng)資源等因素,因此最好將reload()放在代碼最后一行
<h2 id="8.3">8.3 navigator對(duì)象</h2>
navigator對(duì)象的屬性通常用于檢測(cè)顯示網(wǎng)頁的瀏覽器類型
<h3 id="8.3.1">8.3.1 檢測(cè)插件</h3>
非IE:
-
方法:用plungins數(shù)組芥丧,plungins的每一項(xiàng)包含下列屬性:
- name:插件名字
- description:插件描述
- filename:插件文件名
- length:插件所處理的MIME類型數(shù)量
具體:循環(huán)迭代每個(gè)插件并將插件的name與給定的名字比較
-
代碼:
function hasPlungin(name){ name = name.toLowerCase(); for(var i=0;i<navigator.plungins.length;i++){ if(navagator.plungins[i].name.toLoowerCase().indexOf(name)>-1){ return true; } } return false; }
IE:
方法:使用專有的ActiveXObject類型
具體:傳入的參數(shù)是一個(gè)COM標(biāo)識(shí)符紧阔,通過嘗試創(chuàng)建一個(gè)特定插件的實(shí)例來確定有沒有插件
-
代碼:
function hasIEPlungins(name){ try{ new ActiveXObject(name); return true; }catch (ex){ return false; } }
因此在所有瀏覽器中檢測(cè)時(shí)要針對(duì)每個(gè)插件分別創(chuàng)建函數(shù):
//檢測(cè)所有瀏覽器中的Flash
function hasFlash(){
var result = hasPlungin("Flash");
if(!result){
result = hasIEPlungin("ShockwaveFlash.ShockwaveFlash");
}
return result;
}
<h3 id="8.3.2">8.3.2 注冊(cè)處理程序</h3>
<h2 id="8.4">8.4 screen對(duì)象</h2>
用來表現(xiàn)客戶端能力
<h2 id="8.5">8.5 history對(duì)象</h2>
用來保存歷史記錄
-
history.go()方法
- 參數(shù):整數(shù)值(負(fù)數(shù)向后跳轉(zhuǎn),相當(dāng)于后退)或字符串
- 當(dāng)輸入字符串時(shí)续担,會(huì)跳到最近的包含這個(gè)字符串的頁面
- history.back():后退一頁
- history.forward():前進(jìn)一頁
-
length屬性
- 檢測(cè)當(dāng)前頁面是不是用戶打開的第一個(gè)頁面
<h2 id="8.6">8.6 小結(jié)</h2>
- 在使用框架時(shí)擅耽,每個(gè)框架都有自己的window對(duì)象以及所有原生構(gòu)造函數(shù)和其他函數(shù)的副本。每個(gè)框架都保存在frames集合中
- 有一些窗口指針赤拒,可以用來引用其他框架秫筏,包括父框架
- top對(duì)象始終指向最外圍的框架
- parent對(duì)象指向包含當(dāng)前框架的框架
- self對(duì)象回指window
- location對(duì)象可以通過編程方式來訪問瀏覽器的導(dǎo)航系統(tǒng)
- 調(diào)用replace()方法可以導(dǎo)航到一個(gè)新的URL并替換歷史記錄種當(dāng)前顯示的頁面
- navigator對(duì)象提供了與瀏覽器有關(guān)的信息
- screen對(duì)象保存著與客戶端顯示器有關(guān)的信息
- history對(duì)象保存著歷史記錄诱鞠,包括后退和前進(jìn)