<h1 id="8">第8章 BOM</h1>
本章內容主要是
- 理解window對象
- 控制窗口、框架和彈出窗口
- 利用location對象中的頁面信息
- 使用navigator對象了解瀏覽器
<h2 id="8.1">8.1 window對象</h2>
- BOM的核心對象是window,它表示瀏覽器的一個實例。
- window對象既是通過JS訪問瀏覽器窗口的一個接口,又是ES規定的Global對象
- 網頁中定義的熱呢一個對象、變量和函數,都以window作為其Global對象
<h3 id="8.1.1">8.1.1 全局作用域</h3>
所有在全局作用域中聲明的變量、函數都會變成window對象的屬性和方法
定義全局變量和直接在window對象上定義屬性有一點差別:全局變量不能通過delete操作符刪除,而直接在window對象上定義的屬性可以。這是因為使用var語句添加的window屬性有一個名為[[Configurable]]的特性,值被設為false
-
嘗試訪問未聲明的變量會拋出錯誤,但是通過查詢window對象,可以知道某個可能未聲明的變量是否存在
//這樣不會有錯誤。值是undefined var newValue = window.oldValue; //拋出錯誤 var newValue = oldValue;
<h3 id="8.1.2">8.1.2 窗口關系及框架</h3>
- 如果頁面中包含框架(像frameset這種),則每個框架都有自己的window對象,并且保存在frames集合中。
- 在frames集合中,可以通過數值索引(0開始,從左到右,從上到下)或者框架名稱來訪問相應的window對象
- 每個window對象都有一個name屬性,其中包含框架的名稱
top對象:
- top對象始終指向最高(最外)層的框架,也就是瀏覽器窗口,使用它可以確保在一個框架中正確地訪問另一個框架
window對象:
- 在一個框架中的window指向的都是自己那個框架,不是最高層的
parent對象:
- 始終指向當前框架的直接上層框架
- 在某些情況下,parent有可能等于top;在沒有框架的情況下,parent一定等于top(都是window)
self對象:
- 始終指向window
- 引入self只是為了與top和parent對應起來
<h3 id="8.1.3">8.1.3 窗口關系及框架</h3>
跨瀏覽器取得窗口左邊和上邊的位置:
var leftPos = (typeof window.screenLeft == "number")?
window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number")?
window.scrrenTop : window.screenY;
這是因為Safari、Opera和Chrome中存在screenLeft和screenTop屬性,而在Firefox中是scrrenX和ScreenY
無法在跨瀏覽器的條件下取得窗口左邊和上邊的精確坐標值,因為在Firefox和Safari中返回的是整個瀏覽器窗口相對于屏幕的坐標值,在IE、Opera和Chrome中返回的是頁面可見區域(不包括工具欄)到屏幕左邊和上邊的值
將窗口精確地移動到一個新位置的方法:
這兩種方法可能會被瀏覽器禁用。且不適用于框架,只對最外層的window對象使用
-
moveTo()
- 參數:新位置的x和y坐標
-
moveBy()
- 參數:在水平和垂直方向上移動的像素數
<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"){//判斷是不是標準模式
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
}else{
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
調整瀏覽器窗口大小的兩個方法:
與移動窗口位置的兩個方法類似,也有可能被瀏覽器禁用。同樣不適用于框架,只能對最外層的window對象使用
-
resizeTo():
- 參數:瀏覽器窗口的新寬度和新高度
-
resizeBy():
- 參數:新窗口與原窗口的寬度和高度之差
<h3 id="8.1.5">8.1.5 導航和打開窗口</h3>
window.open():
-
參數:要加載的URL、窗口目標、一個特性字符串、一個表示新頁面是否取代瀏覽器歷史記錄中當前加載頁面的布爾值
第一個參數:通常只需傳遞第一個參數。
-
第二個參數:
-
該參數是已有窗口或框架的名稱
- 在指定的窗口或框架中加載指定URL
- 代碼:
//等同于<a target="topFrame"></a>
window.open("http://www.baidu.com/","topFrame");
- 如果沒有窗口或框架的名稱是topFrame,就會創建一個新窗口并將其命名為topFrame
_self
_parent
_top
_blank
-
-
第三個參數:
如果第二個參數并不是已經存在的窗口或框架,那么就會根據在第三個參數位置上傳入的字符串創建一個新窗口或新標簽頁。如果沒有第三個參數,就會打開一個帶有全部默認設置的新瀏覽器窗口
在不打開新窗口的情況下,會忽略第三個參數
是一個用逗號分隔的設置字符串,表示新窗口的特性
-
整個特性字符串中不能有空格,比如:
window.open("http://www.baidu.com/","topFrame","height=400,width=400");
第四個參數:只在不打開新窗口的情況下使用
-
返回:一個指向新窗口的引用
用途:可以針對 通過window.open()創建的窗口 調整大小或移動位置
-
代碼:
var wroxWin = window.open("http://www.baidu.com/","wroxWindow","height=400,width=400"); wroxWin.resizeTo(500,500); wroxWin.moveTo(100,100)
wroxWin.close()
還可以關閉這個新打開的窗口要注意的是對于瀏覽器的主窗口,如果沒有得到用戶允許是不能關閉的(除了彈出窗口可以調用
top.close()
關閉)
-
opener屬性
- 定義于新窗口的最外層window對象(top)中,指向原始窗口(調用
window.open()
的窗口或框架) - 當把opener屬性設置為null時,就是告訴瀏覽器新建的標簽頁不需要與打開它的標簽頁通信,因此可以在獨立的進程中運行。標簽頁的聯系一旦切斷,將沒有辦法恢復
- 定義于新窗口的最外層window對象(top)中,指向原始窗口(調用
彈出窗口屏蔽程序
內置的屏蔽程序阻止彈出窗口:window.open()返回null
-
擴展或其他程序阻止彈出窗口:拋出一個錯誤
因此準確檢測出彈出窗口是否被屏蔽的代碼如下: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 間歇調用和超時調用</h3>
JS是單線程語言,但它允許通過設置超時值和間歇時間值來調度代碼在特定的時刻執行。
-
超時調用:setTimeOut()
-
參數:要執行的代碼和以毫秒表示的時間
- 第一個參數:可以是一個包含JS代碼的字符串(同eval()函數里的字符串),也可以是一個函數
- 不建議以字符串作為第一個參數。因為可能導致性能缺失
- 第二個參數:是一個表示等待多長時間的毫秒數。JS是一個單線程的解釋器,有一個JS任務隊列,這些任務按照將它們添加到隊列 的順序執行。也就是說這個參數只是指定多長時間后把任務添加到隊列。但不一定會立即執行(前面可能還有任務)。
-
返回:一個數值ID,表示超時調用
這個超時調用ID是計劃執行代碼的唯一標識符
-
只要指定的時間尚未過去,就可以取消尚未執行的超時調用計劃:傳入ID
clearTimeOut(timeoutId);
-
-
間歇調用:setInterval()
- 參數:(與setTimeOut()相同)要執行的代碼和以毫秒表示的時間
- 區別:按照指定的時間間隔重復執行代碼,直到間歇調用被取消或者頁面被卸載
- 返回:間歇調用ID
- 取消:
clearInterval(Id)
一個常見的使用間歇調用的例子
var num =0;
var max = 10;
var intervalId = null;
function incrementNumber(){
num++;
//如果執行次數達到max,則取消后續尚未執行的調用
if(num == max){
clearInterval(intervalId);
alert("Done");
}
}
intervalId = setInterval(incrementNumber,500);
與以上代碼相同功能的超時調用:
var num = 0;
var max = 10;
function incrementMunber(){
num++;
if(num < max){
setTimeout(incrementNumber,500);
}else{
alert("Done");
}
}
setTimeout(incrementNumber,500);
比較上面兩段代碼,可以看出超時調用不需要跟蹤超時調用ID。一般認為,使用超時調用模擬間歇調用是一種最佳模式。在開發環境下,很少使用間歇調用,因為后一個間歇調用可能會在前一個間歇調用結束前啟動。所以最好不要使用間歇調用
<h3 id="8.1.7">8.1.7 系統對話框</h3>
以下三個不涉及HTML、CSS、JS
- alert():警告
- confirm():確認
- prompt():提示
- 參數:要顯示給用戶的文本提示和文本輸入域(可以是"")
- 返回:單擊OK則返回文本輸入域的值,單擊cancel或通過其他方式關閉對話框則返回null
以下兩個可以通過JS打開的對話框:查找和打印。這兩個對話框都是異步顯示的,能夠將控制權立即交還給腳本。與用戶通過瀏覽器菜單的查找和打印命令打開的對話框相同
- 打印:
window.print();
- 查找:
window.find();
<h2 id="8.2">8.2 location對象</h2>
location提供了與當前窗口中加載的文檔有關的信息,還提供了一些導航功能。
location既是window對象的屬性,也是document對象的屬性。
location將URL解析為獨立的片段
<h3 id="8.2.1">8.2.1 查詢字符串參數</h3>
以下函數解析查詢字符串,然后返回包含所有參數的一個對象:
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>
以下三種方法本質上都是調用assign()方法,location.href比較常用
location.assign(URL);
window.location = URL;
location.href = URL;
通過改變location對象的其他屬性值來改變當前加載的頁面:
//假設初始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),頁面都會以新URL重新加載
replace()
方法:
作用:禁用后退按鈕
-
示例:訪問該網頁的時候1s后導航到百度,并且后退按鈕被禁用
<!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);//重新加載(從服務器重新加載)
- 位于reload()之后的代碼可能不執行,取決于網絡延遲或系統資源等因素,因此最好將reload()放在代碼最后一行
<h2 id="8.3">8.3 navigator對象</h2>
navigator對象的屬性通常用于檢測顯示網頁的瀏覽器類型
<h3 id="8.3.1">8.3.1 檢測插件</h3>
非IE:
-
方法:用plungins數組,plungins的每一項包含下列屬性:
- name:插件名字
- description:插件描述
- filename:插件文件名
- length:插件所處理的MIME類型數量
具體:循環迭代每個插件并將插件的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類型
具體:傳入的參數是一個COM標識符,通過嘗試創建一個特定插件的實例來確定有沒有插件
-
代碼:
function hasIEPlungins(name){ try{ new ActiveXObject(name); return true; }catch (ex){ return false; } }
因此在所有瀏覽器中檢測時要針對每個插件分別創建函數:
//檢測所有瀏覽器中的Flash
function hasFlash(){
var result = hasPlungin("Flash");
if(!result){
result = hasIEPlungin("ShockwaveFlash.ShockwaveFlash");
}
return result;
}
<h3 id="8.3.2">8.3.2 注冊處理程序</h3>
<h2 id="8.4">8.4 screen對象</h2>
用來表現客戶端能力
<h2 id="8.5">8.5 history對象</h2>
用來保存歷史記錄
-
history.go()方法
- 參數:整數值(負數向后跳轉,相當于后退)或字符串
- 當輸入字符串時,會跳到最近的包含這個字符串的頁面
- history.back():后退一頁
- history.forward():前進一頁
-
length屬性
- 檢測當前頁面是不是用戶打開的第一個頁面
<h2 id="8.6">8.6 小結</h2>
- 在使用框架時,每個框架都有自己的window對象以及所有原生構造函數和其他函數的副本。每個框架都保存在frames集合中
- 有一些窗口指針,可以用來引用其他框架,包括父框架
- top對象始終指向最外圍的框架
- parent對象指向包含當前框架的框架
- self對象回指window
- location對象可以通過編程方式來訪問瀏覽器的導航系統
- 調用replace()方法可以導航到一個新的URL并替換歷史記錄種當前顯示的頁面
- navigator對象提供了與瀏覽器有關的信息
- screen對象保存著與客戶端顯示器有關的信息
- history對象保存著歷史記錄,包括后退和前進