概述
瀏覽器里面,window
對(duì)象(注意,w
為小寫)指當(dāng)前的瀏覽器窗口。它也是當(dāng)前頁(yè)面的頂層對(duì)象,即最高一層的對(duì)象,所有其他對(duì)象都是它的下屬。一個(gè)變量如果未聲明,那么默認(rèn)就是頂層對(duì)象的屬性。
a = 1;
window.a // 1
上面代碼中,a
是一個(gè)沒(méi)有聲明就直接賦值的變量,它自動(dòng)成為頂層對(duì)象的屬性。
window
有自己的實(shí)體含義,其實(shí)不適合當(dāng)作最高一層的頂層對(duì)象,這是一個(gè)語(yǔ)言的設(shè)計(jì)失誤。最早,設(shè)計(jì)這門語(yǔ)言的時(shí)候,原始設(shè)想是語(yǔ)言內(nèi)置的對(duì)象越少越好,這樣可以提高瀏覽器的性能。因此,語(yǔ)言設(shè)計(jì)者 Brendan Eich 就把window
對(duì)象當(dāng)作頂層對(duì)象,所有未聲明就賦值的變量都自動(dòng)變成window
對(duì)象的屬性。這種設(shè)計(jì)使得編譯階段無(wú)法檢測(cè)出未聲明變量,但到了今天已經(jīng)沒(méi)有辦法糾正了。
window 對(duì)象的屬性
window.name
window.name
屬性是一個(gè)字符串,表示當(dāng)前瀏覽器窗口的名字。窗口不一定需要名字,這個(gè)屬性主要配合超鏈接和表單的target
屬性使用。
window.name = 'Hello World!';
console.log(window.name)
// "Hello World!"
該屬性只能保存字符串,如果寫入的值不是字符串,會(huì)自動(dòng)轉(zhuǎn)成字符串。各個(gè)瀏覽器對(duì)這個(gè)值的儲(chǔ)存容量有所不同,但是一般來(lái)說(shuō),可以高達(dá)幾MB。
只要瀏覽器窗口不關(guān)閉,這個(gè)屬性是不會(huì)消失的。舉例來(lái)說(shuō),訪問(wèn)a.com
時(shí),該頁(yè)面的腳本設(shè)置了window.name
,接下來(lái)在同一個(gè)窗口里面載入了b.com
,新頁(yè)面的腳本可以讀到上一個(gè)網(wǎng)頁(yè)設(shè)置的window.name
。頁(yè)面刷新也是這種情況。一旦瀏覽器窗口關(guān)閉后,該屬性保存的值就會(huì)消失,因?yàn)檫@時(shí)窗口已經(jīng)不存在了。
window.closed,window.opener
window.closed
屬性返回一個(gè)布爾值,表示窗口是否關(guān)閉。
window.closed // false
上面代碼檢查當(dāng)前窗口是否關(guān)閉。這種檢查意義不大,因?yàn)橹灰苓\(yùn)行代碼,當(dāng)前窗口肯定沒(méi)有關(guān)閉。這個(gè)屬性一般用來(lái)檢查,使用腳本打開的新窗口是否關(guān)閉。
var popup = window.open();
if ((popup !== null) && !popup.closed) {
// 窗口仍然打開著
}
window.opener
屬性表示打開當(dāng)前窗口的父窗口。如果當(dāng)前窗口沒(méi)有父窗口(即直接在地址欄輸入打開),則返回null
。
window.open().opener === window // true
上面表達(dá)式會(huì)打開一個(gè)新窗口,然后返回true
。
如果兩個(gè)窗口之間不需要通信,建議將子窗口的opener
屬性顯式設(shè)為null
,這樣可以減少一些安全隱患。
var newWin = window.open('example.html', 'newWindow', 'height=400,width=400');
newWin.opener = null;
上面代碼中,子窗口的opener
屬性設(shè)為null
,兩個(gè)窗口之間就沒(méi)辦法再聯(lián)系了。
通過(guò)opener
屬性,可以獲得父窗口的全局屬性和方法,但只限于兩個(gè)窗口同源的情況(參見(jiàn)《同源限制》一章),且其中一個(gè)窗口由另一個(gè)打開。<a>
元素添加rel="noopener"
屬性,可以防止新打開的窗口獲取父窗口,減輕被惡意網(wǎng)站修改父窗口 URL 的風(fēng)險(xiǎn)。
<a rel="external nofollow" target="_blank" target="_blank" rel="noopener">
惡意網(wǎng)站
</a>
window.self,window.window
window.self
和window.window
屬性都指向窗口本身。這兩個(gè)屬性只讀。
window.self === window // true
window.window === window // true
window.frames,window.length
window.frames
屬性返回一個(gè)類似數(shù)組的對(duì)象,成員為頁(yè)面內(nèi)所有框架窗口,包括frame
元素和iframe
元素。window.frames[0]
表示頁(yè)面中第一個(gè)框架窗口。
如果iframe
元素設(shè)置了id
或name
屬性,那么就可以用屬性值,引用這個(gè)iframe
窗口。比如<iframe name="myIFrame">
可以用frames['myIFrame']
或者frames.myIFrame
來(lái)引用。
frames
屬性實(shí)際上是window
對(duì)象的別名。
frames === window // true
因此,frames[0]
也可以用window[0]
表示。但是,從語(yǔ)義上看,frames
更清晰,而且考慮到window
還是全局對(duì)象,因此推薦表示多窗口時(shí),總是使用frames[0]
的寫法。更多介紹請(qǐng)看下文的《多窗口操作》部分。
window.length
屬性返回當(dāng)前網(wǎng)頁(yè)包含的框架總數(shù)。如果當(dāng)前網(wǎng)頁(yè)不包含frame
和iframe
元素,那么window.length
就返回0
。
window.frames.length === window.length // true
上面代碼表示,window.frames.length
與window.length
應(yīng)該是相等的。
window.frameElement
window.frameElement
屬性主要用于當(dāng)前窗口嵌在另一個(gè)網(wǎng)頁(yè)的情況(嵌入<object>
、<iframe>
或<embed>
元素),返回當(dāng)前窗口所在的那個(gè)元素節(jié)點(diǎn)。如果當(dāng)前窗口是頂層窗口,或者所嵌入的那個(gè)網(wǎng)頁(yè)不是同源的,該屬性返回null
。
// HTML 代碼如下
// <iframe src="about.html"></iframe>
// 下面的腳本在 about.html 里面
var frameEl = window.frameElement;
if (frameEl) {
frameEl.src = 'other.html';
}
上面代碼中,frameEl
變量就是<iframe>
元素。
window.top,window.parent
window.top
屬性指向最頂層窗口,主要用于在框架窗口(frame)里面獲取頂層窗口。
window.parent
屬性指向父窗口。如果當(dāng)前窗口沒(méi)有父窗口,window.parent
指向自身。
if (window.parent !== window.top) {
// 表明當(dāng)前窗口嵌入不止一層
}
對(duì)于不包含框架的網(wǎng)頁(yè),這兩個(gè)屬性等同于window
對(duì)象。
window.status
window.status
屬性用于讀寫瀏覽器狀態(tài)欄的文本。但是,現(xiàn)在很多瀏覽器都不允許改寫狀態(tài)欄文本,所以使用這個(gè)方法不一定有效。
window.devicePixelRatio
window.devicePixelRatio
屬性返回一個(gè)數(shù)值,表示一個(gè) CSS 像素的大小與一個(gè)物理像素的大小之間的比率。也就是說(shuō),它表示一個(gè) CSS 像素由多少個(gè)物理像素組成。它可以用于判斷用戶的顯示環(huán)境,如果這個(gè)比率較大,就表示用戶正在使用高清屏幕,因此可以顯示較大像素的圖片。
位置大小屬性
以下屬性返回window
對(duì)象的位置信息和大小信息。
(1)window.screenX,window.screenY
window.screenX
和window.screenY
屬性,返回瀏覽器窗口左上角相對(duì)于當(dāng)前屏幕左上角的水平距離和垂直距離(單位像素)。這兩個(gè)屬性只讀。
(2) window.innerHeight,window.innerWidth
window.innerHeight
和window.innerWidth
屬性,返回網(wǎng)頁(yè)在當(dāng)前窗口中可見(jiàn)部分的高度和寬度,即“視口”(viewport)的大?。▎挝幌袼兀?。這兩個(gè)屬性只讀。
用戶放大網(wǎng)頁(yè)的時(shí)候(比如將網(wǎng)頁(yè)從100%的大小放大為200%),這兩個(gè)屬性會(huì)變小。因?yàn)檫@時(shí)網(wǎng)頁(yè)的像素大小不變(比如寬度還是960像素),只是每個(gè)像素占據(jù)的屏幕空間變大了,因此可見(jiàn)部分(視口)就變小了。
注意,這兩個(gè)屬性值包括滾動(dòng)條的高度和寬度。
(3)window.outerHeight,window.outerWidth
window.outerHeight
和window.outerWidth
屬性返回瀏覽器窗口的高度和寬度,包括瀏覽器菜單和邊框(單位像素)。這兩個(gè)屬性只讀。
(4)window.scrollX,window.scrollY
window.scrollX
屬性返回頁(yè)面的水平滾動(dòng)距離,window.scrollY
屬性返回頁(yè)面的垂直滾動(dòng)距離,單位都為像素。這兩個(gè)屬性只讀。
注意,這兩個(gè)屬性的返回值不是整數(shù),而是雙精度浮點(diǎn)數(shù)。如果頁(yè)面沒(méi)有滾動(dòng),它們的值就是0
。
舉例來(lái)說(shuō),如果用戶向下拉動(dòng)了垂直滾動(dòng)條75像素,那么window.scrollY
就是75左右。用戶水平向右拉動(dòng)水平滾動(dòng)條200像素,window.scrollX
就是200左右。
if (window.scrollY < 75) {
window.scroll(0, 75);
}
上面代碼中,如果頁(yè)面向下滾動(dòng)的距離小于75像素,那么頁(yè)面向下滾動(dòng)75像素。
(5)window.pageXOffset,window.pageYOffset
window.pageXOffset
屬性和window.pageYOffset
屬性,是window.scrollX
和window.scrollY
別名。
組件屬性
組件屬性返回瀏覽器的組件對(duì)象。這樣的屬性有下面幾個(gè)。
window.locationbar
:地址欄對(duì)象window.menubar
:菜單欄對(duì)象window.scrollbars
:窗口的滾動(dòng)條對(duì)象window.toolbar
:工具欄對(duì)象window.statusbar
:狀態(tài)欄對(duì)象window.personalbar
:用戶安裝的個(gè)人工具欄對(duì)象
這些對(duì)象的visible
屬性是一個(gè)布爾值,表示這些組件是否可見(jiàn)。這些屬性只讀。
window.locationbar.visible
window.menubar.visible
window.scrollbars.visible
window.toolbar.visible
window.statusbar.visible
window.personalbar.visible
全局對(duì)象屬性
全局對(duì)象屬性指向一些瀏覽器原生的全局對(duì)象。
window.document
:指向document
對(duì)象,詳見(jiàn)《document 對(duì)象》一章。注意,這個(gè)屬性有同源限制。只有來(lái)自同源的腳本才能讀取這個(gè)屬性。window.location
:指向Location
對(duì)象,用于獲取當(dāng)前窗口的 URL 信息。它等同于document.location
屬性,詳見(jiàn)《Location 對(duì)象》一章。window.navigator
:指向Navigator
對(duì)象,用于獲取環(huán)境信息,詳見(jiàn)《Navigator 對(duì)象》一章。window.history
:指向History
對(duì)象,表示瀏覽器的瀏覽歷史,詳見(jiàn)《History 對(duì)象》一章。window.localStorage
:指向本地儲(chǔ)存的 localStorage 數(shù)據(jù),詳見(jiàn)《Storage 接口》一章。window.sessionStorage
:指向本地儲(chǔ)存的 sessionStorage 數(shù)據(jù),詳見(jiàn)《Storage 接口》一章。window.console
:指向console
對(duì)象,用于操作控制臺(tái),詳見(jiàn)《console 對(duì)象》一章。window.screen
:指向Screen
對(duì)象,表示屏幕信息,詳見(jiàn)《Screen 對(duì)象》一章。
window.isSecureContext
window.isSecureContext
屬性返回一個(gè)布爾值,表示當(dāng)前窗口是否處在加密環(huán)境。如果是 HTTPS 協(xié)議,就是true
,否則就是false
。
window 對(duì)象的方法
window.alert(),window.prompt(),window.confirm()
window.alert()
、window.prompt()
、window.confirm()
都是瀏覽器與用戶互動(dòng)的全局方法。它們會(huì)彈出不同的對(duì)話框,要求用戶做出回應(yīng)。注意,這三個(gè)方法彈出的對(duì)話框,都是瀏覽器統(tǒng)一規(guī)定的式樣,無(wú)法定制。
(1)window.alert()
window.alert()
方法彈出的對(duì)話框,只有一個(gè)“確定”按鈕,往往用來(lái)通知用戶某些信息。
window.alert('Hello World');
用戶只有點(diǎn)擊“確定”按鈕,對(duì)話框才會(huì)消失。對(duì)話框彈出期間,瀏覽器窗口處于凍結(jié)狀態(tài),如果不點(diǎn)“確定”按鈕,用戶什么也干不了。
window.alert()
方法的參數(shù)只能是字符串,沒(méi)法使用 CSS 樣式,但是可以用\n
指定換行。
alert('本條提示\n分成兩行');
(2)window.prompt()
window.prompt()
方法彈出的對(duì)話框,提示文字的下方,還有一個(gè)輸入框,要求用戶輸入信息,并有“確定”和“取消”兩個(gè)按鈕。它往往用來(lái)獲取用戶輸入的數(shù)據(jù)。
var result = prompt('您的年齡?', 25)
上面代碼會(huì)跳出一個(gè)對(duì)話框,文字提示為“您的年齡?”,要求用戶在對(duì)話框中輸入自己的年齡(默認(rèn)顯示25)。用戶填入的值,會(huì)作為返回值存入變量result
。
window.prompt()
的返回值有兩種情況,可能是字符串(有可能是空字符串),也有可能是null
。具體分成三種情況。
- 用戶輸入信息,并點(diǎn)擊“確定”,則用戶輸入的信息就是返回值。
- 用戶沒(méi)有輸入信息,直接點(diǎn)擊“確定”,則輸入框的默認(rèn)值就是返回值。
- 用戶點(diǎn)擊了“取消”(或者按了 ESC 按鈕),則返回值是
null
。
window.prompt()
方法的第二個(gè)參數(shù)是可選的,但是最好總是提供第二個(gè)參數(shù),作為輸入框的默認(rèn)值。
(3)window.confirm()
window.confirm()
方法彈出的對(duì)話框,除了提示信息之外,只有“確定”和“取消”兩個(gè)按鈕,往往用來(lái)征詢用戶是否同意。
var result = confirm('你最近好嗎?');
上面代碼彈出一個(gè)對(duì)話框,上面只有一行文字“你最近好嗎?”,用戶選擇點(diǎn)擊“確定”或“取消”。
confirm
方法返回一個(gè)布爾值,如果用戶點(diǎn)擊“確定”,返回true
;如果用戶點(diǎn)擊“取消”,則返回false
。
var okay = confirm('Please confirm this message.');
if (okay) {
// 用戶按下“確定”
} else {
// 用戶按下“取消”
}
confirm
的一個(gè)用途是,用戶離開當(dāng)前頁(yè)面時(shí),彈出一個(gè)對(duì)話框,問(wèn)用戶是否真的要離開。
window.onunload = function () {
return window.confirm('你確定要離開當(dāng)面頁(yè)面嗎?');
}
這三個(gè)方法都具有堵塞效應(yīng),一旦彈出對(duì)話框,整個(gè)頁(yè)面就是暫停執(zhí)行,等待用戶做出反應(yīng)。
window.open(), window.close(),window.stop()
(1)window.open()
window.open
方法用于新建另一個(gè)瀏覽器窗口,類似于瀏覽器菜單的新建窗口選項(xiàng)。它會(huì)返回新窗口的引用,如果無(wú)法新建窗口,則返回null
。
var popup = window.open('somefile.html');
上面代碼會(huì)讓瀏覽器彈出一個(gè)新建窗口,網(wǎng)址是當(dāng)前域名下的somefile.html
。
open
方法一共可以接受三個(gè)參數(shù)。
window.open(url, windowName, [windowFeatures])
url
:字符串,表示新窗口的網(wǎng)址。如果省略,默認(rèn)網(wǎng)址就是about:blank
。windowName
:字符串,表示新窗口的名字。如果該名字的窗口已經(jīng)存在,則占用該窗口,不再新建窗口。如果省略,就默認(rèn)使用_blank
,表示新建一個(gè)沒(méi)有名字的窗口。另外還有幾個(gè)預(yù)設(shè)值,_self
表示當(dāng)前窗口,_top
表示頂層窗口,_parent
表示上一層窗口。windowFeatures
:字符串,內(nèi)容為逗號(hào)分隔的鍵值對(duì)(詳見(jiàn)下文),表示新窗口的參數(shù),比如有沒(méi)有提示欄、工具條等等。如果省略,則默認(rèn)打開一個(gè)完整 UI 的新窗口。如果新建的是一個(gè)已經(jīng)存在的窗口,則該參數(shù)不起作用,瀏覽器沿用以前窗口的參數(shù)。
下面是一個(gè)例子。
var popup = window.open(
'somepage.html',
'DefinitionsWindows',
'height=200,width=200,location=no,status=yes,resizable=yes,scrollbars=yes'
);
上面代碼表示,打開的新窗口高度和寬度都為200像素,沒(méi)有地址欄,但有狀態(tài)欄和滾動(dòng)條,允許用戶調(diào)整大小。
第三個(gè)參數(shù)可以設(shè)定如下屬性。
- left:新窗口距離屏幕最左邊的距離(單位像素)。注意,新窗口必須是可見(jiàn)的,不能設(shè)置在屏幕以外的位置。
- top:新窗口距離屏幕最頂部的距離(單位像素)。
- height:新窗口內(nèi)容區(qū)域的高度(單位像素),不得小于100。
- width:新窗口內(nèi)容區(qū)域的寬度(單位像素),不得小于100。
- outerHeight:整個(gè)瀏覽器窗口的高度(單位像素),不得小于100。
- outerWidth:整個(gè)瀏覽器窗口的寬度(單位像素),不得小于100。
- menubar:是否顯示菜單欄。
- toolbar:是否顯示工具欄。
- location:是否顯示地址欄。
- personalbar:是否顯示用戶自己安裝的工具欄。
- status:是否顯示狀態(tài)欄。
- dependent:是否依賴父窗口。如果依賴,那么父窗口最小化,該窗口也最小化;父窗口關(guān)閉,該窗口也關(guān)閉。
- minimizable:是否有最小化按鈕,前提是
dialog=yes
。 - noopener:新窗口將與父窗口切斷聯(lián)系,即新窗口的
window.opener
屬性返回null
,父窗口的window.open()
方法也返回null
。 - resizable:新窗口是否可以調(diào)節(jié)大小。
- scrollbars:是否允許新窗口出現(xiàn)滾動(dòng)條。
- dialog:新窗口標(biāo)題欄是否出現(xiàn)最大化、最小化、恢復(fù)原始大小的控件。
- titlebar:新窗口是否顯示標(biāo)題欄。
- alwaysRaised:是否顯示在所有窗口的頂部。
- alwaysLowered:是否顯示在父窗口的底下。
- close:新窗口是否顯示關(guān)閉按鈕。
對(duì)于那些可以打開和關(guān)閉的屬性,設(shè)為yes
或1
或不設(shè)任何值就表示打開,比如status=yes
、status=1
、status
都會(huì)得到同樣的結(jié)果。如果想設(shè)為關(guān)閉,不用寫no
,而是直接省略這個(gè)屬性即可。也就是說(shuō),如果在第三個(gè)參數(shù)中設(shè)置了一部分屬性,其他沒(méi)有被設(shè)置的yes/no
屬性都會(huì)被設(shè)成no
,只有titlebar
和關(guān)閉按鈕除外(它們的值默認(rèn)為yes
)。
上面這些屬性,屬性名與屬性值之間用等號(hào)連接,屬性與屬性之間用逗號(hào)分隔。
'height=200,width=200,location=no,status=yes,resizable=yes,scrollbars=yes'
另外,open()
方法的第二個(gè)參數(shù)雖然可以指定已經(jīng)存在的窗口,但是不等于可以任意控制其他窗口。為了防止被不相干的窗口控制,瀏覽器只有在兩個(gè)窗口同源,或者目標(biāo)窗口被當(dāng)前網(wǎng)頁(yè)打開的情況下,才允許open
方法指向該窗口。
window.open
方法返回新窗口的引用。
var windowB = window.open('windowB.html', 'WindowB');
windowB.window.name // "WindowB"
注意,如果新窗口和父窗口不是同源的(即不在同一個(gè)域),它們彼此不能獲取對(duì)方窗口對(duì)象的內(nèi)部屬性。
下面是另一個(gè)例子。
var w = window.open();
console.log('已經(jīng)打開新窗口');
w.location = 'http://example.com';
上面代碼先打開一個(gè)新窗口,然后在該窗口彈出一個(gè)對(duì)話框,再將網(wǎng)址導(dǎo)向example.com
。
由于open
這個(gè)方法很容易被濫用,許多瀏覽器默認(rèn)都不允許腳本自動(dòng)新建窗口。只允許在用戶點(diǎn)擊鏈接或按鈕時(shí),腳本做出反應(yīng),彈出新窗口。因此,有必要檢查一下打開新窗口是否成功。
var popup = window.open();
if (popup === null) {
// 新建窗口失敗
}
(2)window.close()
window.close
方法用于關(guān)閉當(dāng)前窗口,一般只用來(lái)關(guān)閉window.open
方法新建的窗口。
popup.close()
該方法只對(duì)頂層窗口有效,iframe
框架之中的窗口使用該方法無(wú)效。
(3)window.stop()
window.stop()
方法完全等同于單擊瀏覽器的停止按鈕,會(huì)停止加載圖像、視頻等正在或等待加載的對(duì)象。
window.stop()
window.moveTo(),window.moveBy()
window.moveTo()
方法用于移動(dòng)瀏覽器窗口到指定位置。它接受兩個(gè)參數(shù),分別是窗口左上角距離屏幕左上角的水平距離和垂直距離,單位為像素。
window.moveTo(100, 200)
上面代碼將窗口移動(dòng)到屏幕(100, 200)
的位置。
window.moveBy()
方法將窗口移動(dòng)到一個(gè)相對(duì)位置。它接受兩個(gè)參數(shù),分別是窗口左上角向右移動(dòng)的水平距離和向下移動(dòng)的垂直距離,單位為像素。
window.moveBy(25, 50)
上面代碼將窗口向右移動(dòng)25像素、向下移動(dòng)50像素。
為了防止有人濫用這兩個(gè)方法,隨意移動(dòng)用戶的窗口,目前只有一種情況,瀏覽器允許用腳本移動(dòng)窗口:該窗口是用window.open()
方法新建的,并且窗口里只有它一個(gè) Tab 頁(yè)。除此以外的情況,使用上面兩個(gè)方法都是無(wú)效的。
window.resizeTo(),window.resizeBy()
window.resizeTo()
方法用于縮放窗口到指定大小。
它接受兩個(gè)參數(shù),第一個(gè)是縮放后的窗口寬度(outerWidth
屬性,包含滾動(dòng)條、標(biāo)題欄等等),第二個(gè)是縮放后的窗口高度(outerHeight
屬性)。
window.resizeTo(
window.screen.availWidth / 2,
window.screen.availHeight / 2
)
上面代碼將當(dāng)前窗口縮放到,屏幕可用區(qū)域的一半寬度和高度。
window.resizeBy()
方法用于縮放窗口。它與window.resizeTo()
的區(qū)別是,它按照相對(duì)的量縮放,window.resizeTo()
需要給出縮放后的絕對(duì)大小。
它接受兩個(gè)參數(shù),第一個(gè)是水平縮放的量,第二個(gè)是垂直縮放的量,單位都是像素。
window.resizeBy(-200, -200)
上面的代碼將當(dāng)前窗口的寬度和高度,都縮小200像素。
window.scrollTo(),window.scroll(),window.scrollBy()
window.scrollTo
方法用于將文檔滾動(dòng)到指定位置。它接受兩個(gè)參數(shù),表示滾動(dòng)后位于窗口左上角的頁(yè)面坐標(biāo)。
window.scrollTo(x-coord, y-coord)
它也可以接受一個(gè)配置對(duì)象作為參數(shù)。
window.scrollTo(options)
配置對(duì)象options
有三個(gè)屬性。
top
:滾動(dòng)后頁(yè)面左上角的垂直坐標(biāo),即 y 坐標(biāo)。left
:滾動(dòng)后頁(yè)面左上角的水平坐標(biāo),即 x 坐標(biāo)。behavior
:字符串,表示滾動(dòng)的方式,有三個(gè)可能值(smooth
、instant
、auto
),默認(rèn)值為auto
。
window.scrollTo({
top: 1000,
behavior: 'smooth'
});
window.scroll()
方法是window.scrollTo()
方法的別名。
window.scrollBy()
方法用于將網(wǎng)頁(yè)滾動(dòng)指定距離(單位像素)。它接受兩個(gè)參數(shù):水平向右滾動(dòng)的像素,垂直向下滾動(dòng)的像素。
window.scrollBy(0, window.innerHeight)
上面代碼用于將網(wǎng)頁(yè)向下滾動(dòng)一屏。
如果不是要滾動(dòng)整個(gè)文檔,而是要滾動(dòng)某個(gè)元素,可以使用下面三個(gè)屬性和方法。
- Element.scrollTop
- Element.scrollLeft
- Element.scrollIntoView()
window.print()
window.print
方法會(huì)跳出打印對(duì)話框,與用戶點(diǎn)擊菜單里面的“打印”命令效果相同。
常見(jiàn)的打印按鈕代碼如下。
document.getElementById('printLink').onclick = function () {
window.print();
}
非桌面設(shè)備(比如手機(jī))可能沒(méi)有打印功能,這時(shí)可以這樣判斷。
if (typeof window.print === 'function') {
// 支持打印功能
}
window.focus(),window.blur()
window.focus()
方法會(huì)激活窗口,使其獲得焦點(diǎn),出現(xiàn)在其他窗口的前面。
var popup = window.open('popup.html', 'Popup Window');
if ((popup !== null) && !popup.closed) {
popup.focus();
}
上面代碼先檢查popup
窗口是否依然存在,確認(rèn)后激活該窗口。
window.blur()
方法將焦點(diǎn)從窗口移除。
當(dāng)前窗口獲得焦點(diǎn)時(shí),會(huì)觸發(fā)focus
事件;當(dāng)前窗口失去焦點(diǎn)時(shí),會(huì)觸發(fā)blur
事件。
window.getSelection()
window.getSelection
方法返回一個(gè)Selection
對(duì)象,表示用戶現(xiàn)在選中的文本。
var selObj = window.getSelection();
使用Selection
對(duì)象的toString
方法可以得到選中的文本。
var selectedText = selObj.toString();
window.getComputedStyle(),window.matchMedia()
window.getComputedStyle()
方法接受一個(gè)元素節(jié)點(diǎn)作為參數(shù),返回一個(gè)包含該元素的最終樣式信息的對(duì)象,詳見(jiàn)《CSS 操作》一章。
window.matchMedia()
方法用來(lái)檢查 CSS 的mediaQuery
語(yǔ)句,詳見(jiàn)《CSS 操作》一章。
window.requestAnimationFrame()
window.requestAnimationFrame()
方法跟setTimeout
類似,都是推遲某個(gè)函數(shù)的執(zhí)行。不同之處在于,setTimeout
必須指定推遲的時(shí)間,window.requestAnimationFrame()
則是推遲到瀏覽器下一次重流時(shí)執(zhí)行,執(zhí)行完才會(huì)進(jìn)行下一次重繪。重繪通常是 16ms 執(zhí)行一次,不過(guò)瀏覽器會(huì)自動(dòng)調(diào)節(jié)這個(gè)速率,比如網(wǎng)頁(yè)切換到后臺(tái) Tab 頁(yè)時(shí),requestAnimationFrame()
會(huì)暫停執(zhí)行。
如果某個(gè)函數(shù)會(huì)改變網(wǎng)頁(yè)的布局,一般就放在window.requestAnimationFrame()
里面執(zhí)行,這樣可以節(jié)省系統(tǒng)資源,使得網(wǎng)頁(yè)效果更加平滑。因?yàn)槁僭O(shè)備會(huì)用較慢的速率重流和重繪,而速度更快的設(shè)備會(huì)有更快的速率。
該方法接受一個(gè)回調(diào)函數(shù)作為參數(shù)。
window.requestAnimationFrame(callback)
上面代碼中,callback
是一個(gè)回調(diào)函數(shù)。callback
執(zhí)行時(shí),它的參數(shù)就是系統(tǒng)傳入的一個(gè)高精度時(shí)間戳(performance.now()
的返回值),單位是毫秒,表示距離網(wǎng)頁(yè)加載的時(shí)間。
window.requestAnimationFrame()
的返回值是一個(gè)整數(shù),這個(gè)整數(shù)可以傳入window.cancelAnimationFrame()
,用來(lái)取消回調(diào)函數(shù)的執(zhí)行。
下面是一個(gè)window.requestAnimationFrame()
執(zhí)行網(wǎng)頁(yè)動(dòng)畫的例子。
var element = document.getElementById('animate');
element.style.position = 'absolute';
var start = null;
function step(timestamp) {
if (!start) start = timestamp;
var progress = timestamp - start;
// 元素不斷向左移,最大不超過(guò)200像素
element.style.left = Math.min(progress / 10, 200) + 'px';
// 如果距離第一次執(zhí)行不超過(guò) 2000 毫秒,
// 就繼續(xù)執(zhí)行動(dòng)畫
if (progress < 2000) {
window.requestAnimationFrame(step);
}
}
window.requestAnimationFrame(step);
上面代碼定義了一個(gè)網(wǎng)頁(yè)動(dòng)畫,持續(xù)時(shí)間是2秒,會(huì)讓元素向右移動(dòng)。
window.requestIdleCallback()
window.requestIdleCallback()
跟setTimeout
類似,也是將某個(gè)函數(shù)推遲執(zhí)行,但是它保證將回調(diào)函數(shù)推遲到系統(tǒng)資源空閑時(shí)執(zhí)行。也就是說(shuō),如果某個(gè)任務(wù)不是很關(guān)鍵,就可以使用window.requestIdleCallback()
將其推遲執(zhí)行,以保證網(wǎng)頁(yè)性能。
它跟window.requestAnimationFrame()
的區(qū)別在于,后者指定回調(diào)函數(shù)在下一次瀏覽器重排時(shí)執(zhí)行,問(wèn)題在于下一次重排時(shí),系統(tǒng)資源未必空閑,不一定能保證在16毫秒之內(nèi)完成;window.requestIdleCallback()
可以保證回調(diào)函數(shù)在系統(tǒng)資源空閑時(shí)執(zhí)行。
該方法接受一個(gè)回調(diào)函數(shù)和一個(gè)配置對(duì)象作為參數(shù)。配置對(duì)象可以指定一個(gè)推遲執(zhí)行的最長(zhǎng)時(shí)間,如果過(guò)了這個(gè)時(shí)間,回調(diào)函數(shù)不管系統(tǒng)資源有無(wú)空閑,都會(huì)執(zhí)行。
window.requestIdleCallback(callback[, options])
callback
參數(shù)是一個(gè)回調(diào)函數(shù)。該回調(diào)函數(shù)執(zhí)行時(shí),系統(tǒng)會(huì)傳入一個(gè)IdleDeadline
對(duì)象作為參數(shù)。IdleDeadline
對(duì)象有一個(gè)didTimeout
屬性(布爾值,表示是否為超時(shí)調(diào)用)和一個(gè)timeRemaining()
方法(返回該空閑時(shí)段剩余的毫秒數(shù))。
options
參數(shù)是一個(gè)配置對(duì)象,目前只有timeout
一個(gè)屬性,用來(lái)指定回調(diào)函數(shù)推遲執(zhí)行的最大毫秒數(shù)。該參數(shù)可選。
window.requestIdleCallback()
方法返回一個(gè)整數(shù)。該整數(shù)可以傳入window.cancelIdleCallback()
取消回調(diào)函數(shù)。
下面是一個(gè)例子。
requestIdleCallback(myNonEssentialWork);
function myNonEssentialWork(deadline) {
while (deadline.timeRemaining() > 0) {
doWorkIfNeeded();
}
}
上面代碼中,requestIdleCallback()
用來(lái)執(zhí)行非關(guān)鍵任務(wù)myNonEssentialWork
。該任務(wù)先確認(rèn)本次空閑時(shí)段有剩余時(shí)間,然后才真正開始執(zhí)行任務(wù)。
下面是指定timeout
的例子。
requestIdleCallback(processPendingAnalyticsEvents, { timeout: 2000 });
上面代碼指定,processPendingAnalyticsEvents
必須在未來(lái)2秒之內(nèi)執(zhí)行。
如果由于超時(shí)導(dǎo)致回調(diào)函數(shù)執(zhí)行,則deadline.timeRemaining()
返回0
,deadline.didTimeout
返回true
。
如果多次執(zhí)行window.requestIdleCallback()
,指定多個(gè)回調(diào)函數(shù),那么這些回調(diào)函數(shù)將排成一個(gè)隊(duì)列,按照先進(jìn)先出的順序執(zhí)行。
事件
window
對(duì)象可以接收以下事件。
load 事件和 onload 屬性
load
事件發(fā)生在文檔在瀏覽器窗口加載完畢時(shí)。window.onload
屬性可以指定這個(gè)事件的回調(diào)函數(shù)。
window.onload = function() {
var elements = document.getElementsByClassName('example');
for (var i = 0; i < elements.length; i++) {
var elt = elements[i];
// ...
}
};
上面代碼在網(wǎng)頁(yè)加載完畢后,獲取指定元素并進(jìn)行處理。
error 事件和 onerror 屬性
瀏覽器腳本發(fā)生錯(cuò)誤時(shí),會(huì)觸發(fā)window
對(duì)象的error
事件。我們可以通過(guò)window.onerror
屬性對(duì)該事件指定回調(diào)函數(shù)。
window.onerror = function (message, filename, lineno, colno, error) {
console.log("出錯(cuò)了!--> %s", error.stack);
};
由于歷史原因,window
的error
事件的回調(diào)函數(shù)不接受錯(cuò)誤對(duì)象作為參數(shù),而是一共可以接受五個(gè)參數(shù),它們的含義依次如下。
- 出錯(cuò)信息
- 出錯(cuò)腳本的網(wǎng)址
- 行號(hào)
- 列號(hào)
- 錯(cuò)誤對(duì)象
老式瀏覽器只支持前三個(gè)參數(shù)。
并不是所有的錯(cuò)誤,都會(huì)觸發(fā) JavaScript 的error
事件(即讓 JavaScript 報(bào)錯(cuò))。一般來(lái)說(shuō),只有 JavaScript 腳本的錯(cuò)誤,才會(huì)觸發(fā)這個(gè)事件,而像資源文件不存在之類的錯(cuò)誤,都不會(huì)觸發(fā)。
下面是一個(gè)例子,如果整個(gè)頁(yè)面未捕獲錯(cuò)誤超過(guò)3個(gè),就顯示警告。
window.onerror = function(msg, url, line) {
if (onerror.num++ > onerror.max) {
alert('ERROR: ' + msg + '\n' + url + ':' + line);
return true;
}
}
onerror.max = 3;
onerror.num = 0;
需要注意的是,如果腳本網(wǎng)址與網(wǎng)頁(yè)網(wǎng)址不在同一個(gè)域(比如使用了 CDN),瀏覽器根本不會(huì)提供詳細(xì)的出錯(cuò)信息,只會(huì)提示出錯(cuò),錯(cuò)誤類型是“Script error.”,行號(hào)為0,其他信息都沒(méi)有。這是瀏覽器防止向外部腳本泄漏信息。一個(gè)解決方法是在腳本所在的服務(wù)器,設(shè)置Access-Control-Allow-Origin
的 HTTP 頭信息。
Access-Control-Allow-Origin: *
然后,在網(wǎng)頁(yè)的<script>
標(biāo)簽中設(shè)置crossorigin
屬性。
<script crossorigin="anonymous" src="http://example.com/file.js" rel="external nofollow" ></script>
上面代碼的crossorigin="anonymous"
表示,讀取文件不需要身份信息,即不需要 cookie 和 HTTP 認(rèn)證信息。如果設(shè)為crossorigin="use-credentials"
,就表示瀏覽器會(huì)上傳 cookie 和 HTTP 認(rèn)證信息,同時(shí)還需要服務(wù)器端打開 HTTP 頭信息Access-Control-Allow-Credentials
。
window 對(duì)象的事件監(jiān)聽(tīng)屬性
除了具備元素節(jié)點(diǎn)都有的 GlobalEventHandlers 接口,window
對(duì)象還具有以下的事件監(jiān)聽(tīng)函數(shù)屬性。
window.onafterprint
:afterprint
事件的監(jiān)聽(tīng)函數(shù)。window.onbeforeprint
:beforeprint
事件的監(jiān)聽(tīng)函數(shù)。window.onbeforeunload
:beforeunload
事件的監(jiān)聽(tīng)函數(shù)。window.onhashchange
:hashchange
事件的監(jiān)聽(tīng)函數(shù)。window.onlanguagechange
:languagechange
的監(jiān)聽(tīng)函數(shù)。window.onmessage
:message
事件的監(jiān)聽(tīng)函數(shù)。window.onmessageerror
:MessageError
事件的監(jiān)聽(tīng)函數(shù)。window.onoffline
:offline
事件的監(jiān)聽(tīng)函數(shù)。window.ononline
:online
事件的監(jiān)聽(tīng)函數(shù)。window.onpagehide
:pagehide
事件的監(jiān)聽(tīng)函數(shù)。window.onpageshow
:pageshow
事件的監(jiān)聽(tīng)函數(shù)。window.onpopstate
:popstate
事件的監(jiān)聽(tīng)函數(shù)。window.onstorage
:storage
事件的監(jiān)聽(tīng)函數(shù)。window.onunhandledrejection
:未處理的 Promise 對(duì)象的reject
事件的監(jiān)聽(tīng)函數(shù)。window.onunload
:unload
事件的監(jiān)聽(tīng)函數(shù)。
多窗口操作
由于網(wǎng)頁(yè)可以使用iframe
元素,嵌入其他網(wǎng)頁(yè),因此一個(gè)網(wǎng)頁(yè)之中會(huì)形成多個(gè)窗口。如果子窗口之中又嵌入別的網(wǎng)頁(yè),就會(huì)形成多級(jí)窗口。
窗口的引用
各個(gè)窗口之中的腳本,可以引用其他窗口。瀏覽器提供了一些特殊變量,用來(lái)返回其他窗口。
top
:頂層窗口,即最上層的那個(gè)窗口parent
:父窗口self
:當(dāng)前窗口,即自身
下面代碼可以判斷,當(dāng)前窗口是否為頂層窗口。
if (window.top === window.self) {
// 當(dāng)前窗口是頂層窗口
} else {
// 當(dāng)前窗口是子窗口
}
下面的代碼讓父窗口的訪問(wèn)歷史后退一次。
window.parent.history.back();
與這些變量對(duì)應(yīng),瀏覽器還提供一些特殊的窗口名,供window.open()
方法、<a>
標(biāo)簽、<form>
標(biāo)簽等引用。
_top
:頂層窗口_parent
:父窗口_blank
:新窗口
下面代碼就表示在頂層窗口打開鏈接。
<a href="somepage.html" target="_top">Link</a>
iframe 元素
對(duì)于iframe
嵌入的窗口,document.getElementById
方法可以拿到該窗口的 DOM 節(jié)點(diǎn),然后使用contentWindow
屬性獲得iframe
節(jié)點(diǎn)包含的window
對(duì)象。
var frame = document.getElementById('theFrame');
var frameWindow = frame.contentWindow;
上面代碼中,frame.contentWindow
可以拿到子窗口的window
對(duì)象。然后,在滿足同源限制的情況下,可以讀取子窗口內(nèi)部的屬性。
// 獲取子窗口的標(biāo)題
frameWindow.title
<iframe>
元素的contentDocument
屬性,可以拿到子窗口的document
對(duì)象。
var frame = document.getElementById('theFrame');
var frameDoc = frame.contentDocument;
// 等同于
var frameDoc = frame.contentWindow.document;
<iframe>
元素遵守同源政策,只有當(dāng)父窗口與子窗口在同一個(gè)域時(shí),兩者之間才可以用腳本通信,否則只有使用window.postMessage
方法。
<iframe>
窗口內(nèi)部,使用window.parent
引用父窗口。如果當(dāng)前頁(yè)面沒(méi)有父窗口,則window.parent
屬性返回自身。因此,可以通過(guò)window.parent
是否等于window.self
,判斷當(dāng)前窗口是否為iframe
窗口。
if (window.parent !== window.self) {
// 當(dāng)前窗口是子窗口
}
<iframe>
窗口的window
對(duì)象,有一個(gè)frameElement
屬性,返回<iframe>
在父窗口中的 DOM 節(jié)點(diǎn)。對(duì)于非嵌入的窗口,該屬性等于null
。
var f1Element = document.getElementById('f1');
var f1Window = f1Element.contentWindow;
f1Window.frameElement === f1Element // true
window.frameElement === null // true
window.frames 屬性
window.frames
屬性返回一個(gè)類似數(shù)組的對(duì)象,成員是所有子窗口的window
對(duì)象。可以使用這個(gè)屬性,實(shí)現(xiàn)窗口之間的互相引用。比如,frames[0]
返回第一個(gè)子窗口,frames[1].frames[2]
返回第二個(gè)子窗口內(nèi)部的第三個(gè)子窗口,parent.frames[1]
返回父窗口的第二個(gè)子窗口。
注意,window.frames
每個(gè)成員的值,是框架內(nèi)的窗口(即框架的window
對(duì)象),而不是iframe
標(biāo)簽在父窗口的 DOM 節(jié)點(diǎn)。如果要獲取每個(gè)框架內(nèi)部的 DOM 樹,需要使用window.frames[0].document
的寫法。
另外,如果<iframe>
元素設(shè)置了name
或id
屬性,那么屬性值會(huì)自動(dòng)成為全局變量,并且可以通過(guò)window.frames
屬性引用,返回子窗口的window
對(duì)象。
// HTML 代碼為 <iframe id="myFrame">
window.myFrame // [HTMLIFrameElement]
frames.myframe === myFrame // true
另外,name
屬性的值會(huì)自動(dòng)成為子窗口的名稱,可以用在window.open
方法的第二個(gè)參數(shù),或者<a>
和<frame>
標(biāo)簽的target
屬性。
更多建議: