BOM是瀏覽器對象模型
Window對象
- BOM 的核心對象是window,它表示瀏覽器的一個實例。
- 在瀏覽器中,window 對象有雙重角色,它既是通過JavaScript訪問瀏覽器窗口的一個接口,又是ECMAScript 規定的Global 對象。
- 在網頁中定義的任何一個對象、變量和函數,都以window作為其Global對象,因此有權訪問
parseInt()等方法。
1、全局作用域
- 由于window 對象同時扮演著ECMAScript中Global對象的角色,因此所有在全局作用域中聲明的變量、函數都會變成window 對象的屬性和方法。
var age = 29;
function sayAge(){
alert(this.age);
}
alert(window.age); //29
sayAge(); //29
window.sayAge(); //29
- 定義全局變量與在window對象上直接定義屬性還是有一點差別:全局變量不能通過delete 操作符刪除,而直接在window 對象上的定義的屬性可以。
var age = 29;
window.color = "red";
//在IE < 9 時拋出錯誤,在其他所有瀏覽器中都返回false
delete window.age;
//在IE < 9 時拋出錯誤,在其他所有瀏覽器中都返回true
delete window.color; //returns true
alert(window.age); //29
alert(window.color); //undefined
- 嘗試訪問未聲明的變量會拋出錯誤,但是通過查詢window對象,可以知道某個可能未聲明的變量是否存在。
//這里會拋出錯誤,因為oldValue 未定義
var newValue = oldValue;
//這里不會拋出錯誤,因為這是一次屬性查詢
//newValue 的值是undefined
var newValue = window.oldValue;
2、窗口關系和框架
- 如果頁面中包含框架,那么每個框架都有自己的window對象,并保存在frames集合中。
- 在frames集合中,可以通過數值索引(從0開始,從左至右,從上到下)或者框架名稱來訪問相應的window 對象。
- 每個window 對象都有一個name 屬性,其中包含框架的名稱。
<html>
<head>
<title>Frameset Example</title>
</head>
<frameset rows="160,*">
<frame src="frame.htm" name="topFrame">
<frameset cols="50%,50%">
<frame src="anotherframe.htm" name="leftFrame">
<frame src="yetanotherframe.htm" name="rightFrame">
</frameset>
</frameset>
</html>
- top 對象始終指向最高(最外)層的框架,也就是瀏覽器窗口。使用它可以確保在一個
框架中正確地訪問另一個框架. - 因為對于在一個框架中編寫的任何代碼來說,其中的window對象指向的都是那個框架的特定實例,而非最高層的框架。
- parent(父)對象始終指向當前框架的直接上層框架。
- 在某些情況下,parent 有可能等于top;但在沒有框架的情況下,parent 一定等于
top(此時它們都等于window)
3、窗口位置
- 用來確定和修改window 對象位置的屬性和方法有很多
- IE、Safari、Opera 和Chrome都提供了screenLeft和screenTop屬性,分別用于表示窗口相對于屏幕左邊和上邊的位置。
- Firefox 則在screenX和screenY屬性中提供相同的窗口位置信息,Safari和Chrome也同時支持這兩個屬性。
//跨瀏覽器獲取窗口左邊和上邊的位置
var leftPos = (typeof window.screenLeft == "number") ?
window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ?
window.screenTop : window.screenY;
- 注意問題:如果window 對象是最外層對象,而且瀏覽器窗口緊貼屏幕最上端——即y 軸坐標為0,那么screenTop的值就是位于頁面可見區域上方的瀏覽器工具欄的像素高度。在Chrome、Firefox和Safari中,screenY或screenTop中保存的是整個瀏覽器窗口相對于屏幕的坐標值,即在窗口的y 軸坐標為0 時返回0。
- 兼容問題:Firefox、Safari和Chrome始終返回頁面中每個框架的top.screenX和top.screenY 值。即使在頁面由于被設置了外邊距而發生偏移的情況下,相對于window對象使用screenX 和screenY每次也都會返回相同的值。而IE和Opera則會給出框架相對于屏幕邊界的精確坐標值。最終結果,就是無法在跨瀏覽器的條件下取得窗口左邊和上邊的精確坐標值
- 使用moveTo()和moveBy()方法可能將窗口精確地移動到一個新位置。這兩個方法都接收兩個參數,其中moveTo()接收的是新位置的x和y坐標值,而moveBy()接收的是在水平和垂直方向上移動的像素數。
//將窗口移動到屏幕左上角
window.moveTo(0,0);
//將窗向下移動100 像素
window.moveBy(0,100);
//將窗口移動到(200,300)
window.moveTo(200,300);
//將窗口向左移動50 像素
window.moveBy(-50,0);
- 這兩個方法可能會被瀏覽器禁用;而且,在Opera和IE7(及更高版本)中默認就是禁用的
4、窗口大小
- IE9+、Firefox、Safari、Opera和Chrome均為此提供了4個屬性:innerWidth、innerHeight、outerWidth 和outerHeight。
- 在IE9+、Safari 和Firefox中,outerWidth和outerHeight返回瀏覽器窗口本身的尺寸(無論是從最外層的window 對象還是從某個框架訪問)
- 在Opera 中,outerWidth和outerHeight的值表示頁面視圖容器(Opera中單個標簽頁對應的瀏覽器窗口)的大小
- innerWidth 和innerHeight則表示該容器中頁面視圖區的大小(減去邊框寬度)
- 在Chrome 中,outerWidth、outerHeight與innerWidth、innerHeight返回相同的值,即視口(viewport)大小而非瀏覽器窗口大小。
- IE8 及更早版本沒有提供取得當前瀏覽器窗口尺寸的屬性;不過,它通過DOM提供了頁面可見區域的相關信息。雖然最終無法確定瀏覽器窗口本身的大小,但卻可以取得頁面視口的大小。
var pageWidth = window.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.innerWidth和window.innerHeight保存著可見視口,也就是屏幕上可見頁面區域的大小。移動IE瀏覽器不支持這些屬性,但通過document.documentElement.clientWidth 和document.documentElement.clientHeihgt提供了相同的信息隨著頁面的縮放,這些值也會相應變化。
- 在其他移動瀏覽器中,document.documentElement度量的是布局視口,即渲染后頁面的實際大?。ㄅc可見視口不同,可見視口只是整個頁面中的一小部分)
- 移動IE 瀏覽器把布局視口的信息保存在document.body.clientWidth和document.body.clientHeight 中。這些值不會隨著頁面縮放變化。
- 使用resizeTo()和resizeBy()方法可以調整瀏覽器窗口的大小。這兩個方法都接收兩個參數,其中resizeTo()接收瀏覽器窗口的新寬度和新高度,而resizeBy()接收新窗口與原窗口的寬度和高度之差。
//調整到100×100
window.resizeTo(100, 100);
//調整到200×150
window.resizeBy(100, 50);
//調整到 300×300
window.resizeTo(300, 300);
5、導航和打開窗口
- 使用window.open()方法既可以導航到一個特定的URL,也可以打開一個新的瀏覽器窗口。這個方法可以接收4個參數:要加載的URL、窗口目標、一個特性字符串以及一個表示新頁面是否取代瀏覽器歷史記錄中當前加載頁面的布爾值
//等同于< a target="topFrame"></a>
window.open("http://www.wrox.com/", "topFrame");
/**如果有一個名叫"topFrame"的窗口或者框架,就會在該窗口或框架加載這個URL;否則,就會創建一個新窗口并將其命名為"topFrame"。**/
- 如果給window.open()傳遞的第二個參數并不是一個已經存在的窗口或框架,那么該方法就會根據在第三個參數位置上傳入的字符串創建一個新窗口或新標簽頁.
- 如果沒有傳入第三個參數,那么就會打開一個帶有全部默認設置(工具欄、地址欄和狀態欄等)的新瀏覽器窗口。
- 第三個參數是一個逗號分隔的設置字符串,表示在新窗口中都顯示哪些特性。下表列出了可以出現在這個字符串中的設置選項。
設 置 | 值 | 說 明 |
---|---|---|
fullscreen | yes或no | 表示瀏覽器窗口是否最大化。僅限IE |
height | 數值 | 表示新窗口的高度。不能小于100 |
left | 數值 | 表示新窗口的左坐標。不能是負值 |
location | yes或no | 表示是否在瀏覽器窗口中顯示地址欄。不同瀏覽器的默認值不同。如果設置為no,地址欄可能會隱藏,也可能會被禁用(取決于瀏覽器) |
menubar | yes或no | 表示是否在瀏覽器窗口中顯示菜單欄。默認值為no |
resizable | yes或no | 表示是否可以通過拖動瀏覽器窗口的邊框改變其大小。默認值為no |
scrollbars | yes或no | 表示如果內容在視口中顯示不下,是否允許滾動。默認值為no |
status | yes或no | 表示是否在瀏覽器窗口中顯示狀態欄。默認值為no |
toolbar | yes或no | 表示是否在瀏覽器窗口中顯示工具欄。默認值為no |
top | 數值 | 表示新窗口的上坐標。不能是負值 |
width | 數值 | 表示新窗口的寬度。不能小于100 |
window.open("http://www.wrox.com/","wroxWindow","height=400,width=400,top=10,left=10,resizable=yes");
/**打開一個新的可以調整大小的窗口,窗口初始大小為400×400 像素,并且距屏幕上沿
和左邊各10 像素。**/
- window.open()方法會返回一個指向新窗口的引用。通過這個返回的對象,可以像操作其他窗口一樣操作新打開的窗口。
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
//調整大小
wroxWin.resizeTo(500,500);
//移動位置
wroxWin.moveTo(100,100);
//調用close()方法還可以關閉新打開的窗口。對于瀏覽器的主窗口,如果沒有
//得到用戶的允許是不能關閉它的
wroxWin.close();
alert(wroxWin.closed); //true
- 新創建的window 對象有一個opener屬性,其中保存著打開它的原始窗口對象。這個屬性只在彈出窗口中的最外層window對象(top)中有定義,而且指向調用window.open()的窗口或框架。
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
alert(wroxWin.opener == window); //true
- 在Chrome中,將新創建的標簽頁的opener屬性設置為null,即表示在單獨的進程中運行新標簽頁.
var wroxWin = window.open("http://www.wrox.com/","wroxWindow",
"height=400,width=400,top=10,left=10,resizable=yes");
wroxWin.opener = null;
/**將opener 屬性設置為null就是告訴瀏覽器新創建的標簽頁不需要與打開它的標簽頁通信,因此可以在獨立的進程中運行。標簽頁之間的聯系一旦切斷,將沒有辦法恢復。**/
- 大多數瀏覽器都內置有彈出窗口屏蔽程序,而沒有內置此類程序的瀏覽器,也可以安裝Yahoo!,Toolbar 等帶有內置屏蔽程序的實用工具.
- 如果是瀏覽器內置的屏蔽程序阻止的彈出窗口,那么window.open()很可能會返回null。此時,只要檢測這個返回的值就可以確定彈出窗口是否被屏蔽了。
var wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null){
alert("The popup was blocked!");
}
- 如果是瀏覽器擴展或其他程序阻止的彈出窗口,那么window.open()通常會拋出一個錯誤。因此,要想準確地檢測出彈出窗口是否被屏蔽,必須在檢測返回值的同時,將對window.open()的調用封裝在一個try-catch 塊中。
var blocked = false;
try {
var wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null){
blocked = true;
}
} catch (ex){
blocked = true;
}
if (blocked){
alert("The popup was blocked!");
}
6、間歇調用和超時調用
- JavaScript 是單線程語言,但它允許通過設置超時值和間歇時間值來調度代碼在特定的時刻執行。前者是在指定的時間過后執行代碼,而后者則是每隔指定的時間就執行一次代碼。
- 超時調用需要使用window對象的setTimeout()方法,它接受兩個參數:要執行的代碼和以毫秒表示的時間(即在執行代碼前需要等待多少毫秒)。
- 第一個參數可以是一個包含JavaScript 代碼的字符串,也可以是一個函數。
//由于傳遞字符串可能導致性能損失,不建議傳遞字符串!
setTimeout("alert('Hello world!') ", 1000);
//推薦的調用方式
setTimeout(function() {
alert("Hello world!");
}, 1000);
- 第二個參數是一個表示等待多長時間的毫秒數,但經過該時間后指定的代碼不一定會執行。
【原因】:JavaScript是一個單線程序的解釋器,因此一定時間內只能執行一段代碼。為了控制要執行的代碼,就有一個JavaScript任務隊列。這些任務會按照將它們添加到隊列的順序執行。setTimeout()的第二個參數告訴JavaScript再過多長時間把當前任務添加到隊列中。如果隊列是空的,那么添加的代碼會立即執行;如果隊列不是空的,那么它就要等前面的代碼執行完了以后再執行。 - 調用setTimeout()之后,該方法會返回一個數值ID,表示超時調用。這個超時調用ID 是計劃執行代碼的唯一標識符,可以通過它來取消超時調用。
- 要取消尚未執行的超時調用計劃,可以調用clearTimeout*()方法并將相應的超時調用ID 作為參數傳遞給它。
//設置超時調用
var timeoutId = setTimeout(function() {
alert("Hello world!");
}, 1000);
//注意:把它取消
clearTimeout(timeoutId);
- 間歇調用會按照指定的時間間隔重復執行代碼,直至間歇調用被取消或者頁面被卸載.
- 設置間歇調用的方法是setInterval(),它接受的參數與setTimeout()相同:要執行的代碼(字符串或函數)和每次執行之前需要等待的毫秒數。
//不建議傳遞字符串!
setInterval ("alert('Hello world!') ", 10000);
//推薦的調用方式
setInterval (function() {
alert("Hello world!");
}, 10000);
- 調用setInterval()方法同樣也會返回一個間歇調用ID,該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);
- 這個模式也可以使用超時調用來實現,在使用超時調用時,沒有必要跟蹤超時調用ID,因為每次執行代碼之后,如果不再設置另一次超時調用,調用就會自行停止。
- 一般認為,使用超時調用來模擬間歇調用的是一種最佳模式。在開發環境下,很少使用真正的間歇調用,原因是后一個間歇調用可能會在前一個間歇調用結束之前啟動。使用超時調用,則完全可以避免這一點。
var num = 0;
var max = 10;
function incrementNumber() {
num++;
//如果執行次數未達到max 設定的值,則設置另一次超時調用
if (num < max) {
setTimeout(incrementNumber, 500);
} else {
alert("Done");
}
}
setTimeout(incrementNumber, 500);
7、系統對話框
- 瀏覽器通過alert()、confirm()和prompt()方法可以調用系統對話框向用戶顯示消息。
- 它們的外觀由操作系統及(或)瀏覽器設置決定,而不是由CSS 決定。
- 通過這幾個方法打開的對話框都是同步和模態的。也就是說,顯示這些對話框的時候代碼會停止執行,而關掉這些對話框后代碼又會恢復執行。
//使用alert()生成“警告”對話框
alert("Hello World!");
//調用confirm()方法生成確認框,包含【確認】和【取消】
if (confirm("Are you sure?")) {
alert("I'm so glad you're sure! ");
} else {
alert("I'm sorry to hear you're not sure. ");
}
/**調用prompt()方法生成“提示”框,提示框中除了包含【確認】和【取消】外,還會顯示一個文本輸入域,以供用戶在其中輸入內容。
prompt()方法接受兩個參數:要顯示給用戶的文本提示和文本輸入域的默認值(可以是一個空字符串)。**/
var result = prompt("What is your name? ", "");
if (result !== null) {
alert("Welcome, " + result);
}
- 如果當前腳本在執行過程中會打開兩個或多個對話框,那么從第二個對話框開始,每個對話框中都會顯示一個復選框,以便用戶阻止后續的對話框顯示,除非用戶刷新頁面。
- 還有兩個可以通過JavaScript打開的對話框,即“查找”和“打印”。這兩個對話框都是異步顯示的,能夠將控制權立即交還給腳本。
//顯示“打印”對話框
window.print();
//顯示“查找”對話框
window.find();
好好學習