ECMAScript是JavaScript的核心,但在web使用JavaScript,那么BOM(瀏覽器對象模型)才是真正的核心。
BOM的核心對象是window,它表示瀏覽器的一個實例。
在瀏覽器中,window對象既是JavaScript訪問瀏覽器窗口的一個接口,又是ECMAScript規定的Global對象。也就是說,在網頁中定義的任何一個變量、對象和函數以window作為其Global對象。
1.全局作用域
既然window對象扮演着Global對象,那么所有在全局作用域中聲明的對象、變量和函數都會變成window的屬性和方法。
定義全局變量和在window對象上定義屬性還是有差別的:全局變量不能通過delete刪除,而在window對象上定義的屬性則可以。
1
2
3
4
5
6
7
8
9
|
var
age=28;
window.color=
"red"
;
//在IE<9是拋出錯誤,在其他瀏覽器中都返回false
delete
window.age;
//在IE<9是拋出錯誤,在其他瀏覽器中都返回true
delete
window.color;
//return true
alert(window.age);
//28
alert(window.color);
//undefined
|
在使用var語句添加window屬性時,有一個名為[[Configurable]]的特性,這個特性的值被設置為false,因此這樣定義的屬性不可以通過delete刪除。
在嘗試訪問未聲明的變量會拋出錯誤,但通過查詢window對象,可以知道某個可能未聲明的變量是否存在。
1
2
3
4
|
//這里拋出錯誤,因為oldValue未聲明
var
newValue=oldValue;
//這里不會拋出錯誤,因為這是一次屬性查詢
var
newValue=window.oldValue // alert(newValue);
|
其實很多全局JavaScript對象如localtion和navigator實際上都是window對象的屬性。
2.窗口關系及框架
如果頁面中包含框架,則每個框架都有自己的window對象,並保存在frames集合中。
在frame集合中,可以通過數值索引或框架名來進行訪問。
1
2
3
4
5
6
7
8
9
10
11
12
|
<
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
>
|
就這個例子而言,可以通過window.frames[0]或者window.frames["topFrame"]來引用上方框架。不過最好使用top.frames[0]來訪問框架。
top對象始終指向最高(外)層框架,也就是瀏覽器窗口。使用它可以確保在一個框架中正確地訪問另一個框架。
與top對象相對的還有另一個window對象是parent,parent(父)對象始終指向當前框架的直接上層框架。
還有一個self對象,它始終指向window,實際上self與window可以互相使用,引入self對象的目的就只是為了與top和parent對象對應起來。
所有的這些對象,都是window的屬性,可以使用window.parent或window.top使用它們。
3.窗口位置
多數瀏覽器都提供了screenLeft和screenTop,分別用於表示窗口相對與屏幕左邊和上邊的位置。FF則在screenX和screenY屬性中提供相同的窗口信息,Safari金額Chorme也同時支持這兩個屬性。
使用下面代碼可以跨瀏覽器取得窗口左邊和上邊的位置。
1
2
|
var
leftPos=(
typeof
window.screenLeft==
"number"
)?window.screenLeft:window.screenX;
var
topPos=(
typeof
window.screenTop==
"number"
)?window.screenTop:window.screenY;
|
值得注意的是,在IE和Opera中screenLeft和screenTop中保存的是從屏幕左邊和上邊到window對象表示的頁面可見區域的距離。在Chrome、FF和Safari中,screenY和screenTop中保存的是整個瀏覽器對於屏幕的坐標值。
最終結果就是無法在跨瀏覽器條件下取得窗口左邊和上邊的精確坐標值。
使用moveTo()和moveBy()方法倒是可以將窗口精確的移動到新位置,兩個方法都接收兩個參數,moveTo()接收的是x,y軸的坐標,moveBy()接收的是移動的像素。
1
2
3
4
|
//將屏幕移動到左上方
moveTo(0,0);
//將窗口左移50px
moveBy(-50,0);
|
但是,這兩個方法可能會被瀏覽器禁用。這兩個方法也只適用於最外層的window對象,不適用框架。
4.窗口大小
主流瀏覽器都為確定窗口大小提供了4個屬性:innerWidth、innerHight、outerWidth和outerHight。
在IE9+、Safari和FF中,outerWidth和outerHight返回的是瀏覽器窗口本身的尺寸(無論從哪個框架訪問),但在Opera中,這兩個屬性的值表示頁面視圖容器的大小(單個標簽頁窗口的大小)。而innerWidth、innerHight則表示該容器中頁面視圖的大小(減去邊框的寬度)。但在Chrome中,這4個屬性都表示視口大小而非瀏覽器大小。
IE9之前沒有提供取得瀏覽器窗口尺寸的屬性;不過它通過DOM提供了頁面可視區域的信息。
在IE、FF、Chrome、Opera和Safari中,document.documentElement.clientWidth和document.documentElement.clientHight中保存着頁面視口信息。在IE6下,要在標准模式下有效。如果是混雜模式就必須通過document.body.clientWidth和document.body.clientHight取得相同信息。Chrome則不分標准模式還是混雜模式。
雖然最終無法確定瀏覽器窗口本身的大小,但卻可以取得頁面視口的大小。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
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;
}
}
alert(
"Width: "
+ pageWidth);
alert(
"Height: "
+ pageHeight);
|
對於移動設備,window.innerWidth和window.innerHight保存着可見視口,也就是屏幕上頁面區域的大小。移動IE瀏覽器則要通過document.documentElement.clientWidth和document.documentElement.clientHight獲取相同信息。
使用resizeTo()和resizeBy()方法都可以調整瀏覽器窗口大小,兩個方法都接收兩個參數,resizeTo()接收的是瀏覽器窗口新寬度和新高度,resizeBy()接收的是新窗口和老窗口的寬度差和高度差。
1
2
3
4
|
//調整到100*100
resizeTo(100,100);
//調整到200*150
moveBy(100,50);
|
但是,這兩個方法可能會被瀏覽器禁用。這兩個方法也只適用於最外層的window對象,不適用框架。
5.導航和打開窗口
window.open()方法既可以打開一個特定的URL,也可以打開一個新的瀏覽器窗口。該方法接收4個參數:URL,窗口目標,一個特性字符串和一個表示新頁面是否取代當前頁面的布爾值。
彈出窗口
各項參數
其中yes/no也可使用1/0;pixelvalue為具體的數值,單位象素。
參數|取值范圍|說明
alwaysLowered|yes/no|指定窗口隱藏在所有窗口之后
alwaysRaised|yes/no|指定窗口懸浮在所有窗口之上
depended|yes/no|是否和父窗口同時關閉
directories|yes/no|Nav2和3的目錄欄是否可見
height|pixelvalue|窗口高度
hotkeys|yes/no|在沒菜單欄的窗口中設安全退出熱鍵
innerHeight|pixelvalue|窗口中文檔的像素高度
innerWidth|pixelvalue|窗口中文檔的像素寬度
location|yes/no|位置欄是否可見
menubar|yes/no|菜單欄是否可見
outerHeight|pixelvalue|設定窗口(包括裝飾邊框)的像素高度
outerWidth|pixelvalue|設定窗口(包括裝飾邊框)的像素寬度
resizable|yes/no|窗口大小是否可調整
screenX|pixelvalue|窗口距屏幕左邊界的像素長度
screenY|pixelvalue|窗口距屏幕上邊界的像素長度
scrollbars|yes/no|窗口是否可有滾動欄
titlebar|yes/no|窗口題目欄是否可見
toolbar|yes/no|窗口工具欄是否可見
Width|pixelvalue|窗口的像素寬度
z-look|yes/no|窗口被激活后是否浮在其它窗口之上
1
|
window.open(
'page.html'
,
'newwindow'
,
'height=100,width=400,top=0,left=0,toolbar=no,menubar=no,scrollbars=no,resizable=no,location=no,status=no'
)
|
腳本運行后,page.html將在新窗體newwindow中打開,寬為100,高為400,距屏頂0象素,屏左0象素,無工具條,無菜單條,無滾動條,不可調整大小,無地址欄,無狀態欄。
6.間歇調用和超時調用
JavaScript是單線程語言,但它允許通過設置超時值和間歇時間來調度代碼在特定時刻執行。前者是在指定的時間過后執行代碼,后者則是每個指定的時間就調用一次。
超時調用setTimeout()
setTimeout() 方法接受兩個參數,第一個參數是函數,第二個參數是時間(單位微秒),返回數值ID。
1
2
3
|
setTimeout(
function
() {
alert(
"你好!"
);
},1000);
|
調用setTimeout()后該方法會返回一個數值ID,表示超時調用,可以通過它取消超時調用。
1
2
3
4
5
|
var
timeOutId = setTimeout(
function
() {
alert(
"你好!"
);
},1000);
clearTimeout(timeOutId);
|
間歇調用setInterval()
setInterval()方法接受兩個參數,第一個參數是函數,第二個參數是時間(單位微秒),返回數值ID
1
2
3
|
setInterval(
function
() {
alert(
"你好!"
);
},1000);
|
取消調用clearInterval(),接受一個參數間歇調用ID
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
var
intervalId =
null
;
var
span = document.createElement(
"span"
);
//創建span節點
span.Id=
"time"
;
//設置span的id
document.body.appendChild(span);
//body內添加span
function
incrementNumber () {
var
now =
new
Date
();
var
timeStr = now.toLocaleTimeString();
span.innerText =timeStr;
num++;
if
(num ==
10
) {
clearInterval(intervalId);
//十秒后時間不變了
}
}
intervalId = setInterval(incrementNumber,
1000
);
|
盡量用超時調用替代間歇調用
1
2
3
4
5
6
7
8
9
10
11
|
var
num = 0;
var
max = 10;
function
incrementNumber() {
num++;
if
(num<max) {
setTimeout(incrementNumber,1000);
}
else
{
alert(
"OK"
);
}
}
setTimeout(incrementNumber,1000);
|
7.系統對話框
警告框alert()
1
|
alert(
"歡迎光臨!"
);
|
信息框confirm(),有取消,確定按鈕
1
2
3
4
5
|
if
(confirm(
"你同意嗎?"
)) {
alert(
"同意"
);
}
else
{
alert(
"不同意"
);
}
|
提示框prompt(),用於提示用戶輸入一些文本
1
2
3
4
|
var
result = prompt(
"您尊姓大名?"
,
" "
);
if
(result !==
null
) {
alert(“歡迎光臨,”+result);
}
|