浏览器对象模型BOM
訪問和操作瀏覽器窗口的模型稱為瀏覽器對象模型BOM(Browser Object Model),但習慣上是把所有針對瀏覽器的JavaScript擴展都納入BOM的范疇。BOM提供了一組獨立于網頁內容而與瀏覽器交互的對象,但由于缺乏相關的行業規范,各瀏覽器提供商在很長一段時間內都是按照各自的想法去實現這些對象的,因而瀏覽器之間共有的對象也就成為了事實上的標準,這種局面在HTML5出現后有望得到改觀——HTML5致力于把很多BOM功能寫入正式規范。由于不同瀏覽器之間的差異性,這里總結的主要是一些我認為比較常用的共有的特性,至于開發過程中的兼容性考慮,就交給流行的JS庫吧(比如jQuery、ExtJS)。
先看一下下面的這個BOM對象圖,從整體上對BOM有個認識:
上圖中的window、document和location對象都具有雙重身份:window對象既是ECMAScript規范中的Global對象,也是BOM中的頂級對象;document對象既是BOM頂級對象的一個屬性,也是DOM模型中的頂級對象;location對象既是window對象的屬性,同時也是document對象的屬性。在BOM中,核心是window對象,下面就重點總結一下這個對象,document對象將在學習DOM模型時再做說明。
一、window對象
1、window作為ECMAScript中的Global對象
(1)引用Global對象的屬性和方法時可以省略對象名,因此在引用window對象的屬性和方法時,也可以省略window。
(2)在全局作用域中this和window指向同一個對象,另外,還可以使用self來引用window對象,也即有this===window===self。
(3)在全局作用域中定義的變量和函數也會成為window對象的屬性和方法,但是和直接在window對象上定義屬性還是有區別:
A、全局變量不能使用delete刪除(相當于給window定義屬性時將屬性特性[[Configurable]]賦值為false了),但是直接在window對象上定義的屬性可以使用delete刪除。這里有趣的是,如果同時定義了全局變量和window對象的屬性,則刪除window屬性時不起作用。
B、嘗試訪問未定義的全局變量會拋出異常,但是訪問未定義的window對象的屬性則只是返回undefined。
var age = '29';//全局作用域中定義的變量和函數會成為window對象的屬性和方法,但是不能使用delete刪除 function getAge(){return this.age; } console.info(window.age); // 29 console.info(window.getAge()); // 29 console.info(this == window); // true console.info(this == self); // true console.info(window == self); // true window.age = '23';//直接在window對象上定義屬性,會同時修改全局變量的值,相反,修改全局變量的值,window對象的屬性值也會修改 console.info(age); delete window.age;//既定義了全局變量,又在window對象上定義了屬性,刪除時雖然沒有報錯,但是并沒有起作用 console.info(age); //23 console.info(window.age); //23 window.color = 'red';//直接在window對象上定義屬性,可以使用delete刪除 console.info(window.color); delete window.color; console.info(window.color);//undefined2、window作為BOM中的頂級對象
(1)窗口關系及框架
先來看看在BOM中幾個具有特殊含義的對象top、window、parent、self:
- top:指向最高(最外)層的框架,也就是瀏覽器窗口。
- window:指向當前框架的頂層對象。
- parent:指向當前框架的直接上層框架,在沒有子框架的情況下,parent、window、top和self都相等,在有子框架的情況下,parent有可能等于top,也有不能不相等。
- self:始終指向window,引入self的目的只是為了與top和parent對象對應起來。
如果頁面中包含框架,則每個框架都有自己的window對象,并且保存在父窗口的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>在最外層的頁面中,可以通過下面的方式來訪問其中的框架:
(2)window作為頂層對象的主要方法
| 屬性和方法 | 返回值 | 參數 | 說明 | ||
| 位置方法 | moveTo(x,y) | x和y表示新位置的x和y坐標值 | |||
| moveBy(x,y) | x和y表示在水平和垂直方向上移動的像素數?? | ||||
| 大小方法 | resizeTo(x,y) | x和y表示瀏覽器窗口的新寬度和新高度 | |||
| resizeBy(x,y) | x和y表示瀏覽器窗口的新寬度、新高度和原寬度、原高度的差 | ||||
| 對話框 | 同步 | alert() | ? | 提示文本 | 顯示時包含傳入的字符串和“確定”按鈕 |
| confirm() | 點擊“確認”返回true,點擊“取消”返回false | 確認文本 | 顯示時包含傳入的字符串、“確認”按鈕(返回true)和“取消”按鈕(返回false),常用于確認刪除操作 | ||
| prompt() | 點擊“確認”返回文本輸入內容,點擊“取消”返回null | 提示文本、文本輸入域 | 顯示時包含文本提示、“確認”按鈕(返回文本輸入域的內容)、“取消”按鈕(返回null)和文本輸入域。 | ||
| 異步 | find() | 相當于使用瀏覽器菜單欄的“查找”命令打開對話框 | |||
| print() | 相當于使用瀏覽器菜單欄的“打印”命令打開對話框 | ||||
| 調度 | 超時 | setTimeOut() | 返回一個數值ID表示這個調用 | 執行函數或代碼、執行代碼前需要等待的時間(毫秒) | JavaScript是單線程的,超時調用和循環調用中的時間表示將需要執行的函數或代碼加入到執行隊列的時間,而不是實際執行的時間,加入到執行隊列之后一有資源就會馬上執行。由于這個原因,setInterval()可能存在一些間隔會被跳過執行,也可能間隔時間比預期的小,因此不建議使用循環調用,而采用下面的鏈式超時調用模式: setTimeout(function(){//處理代碼 setTimeout(arguments.callee, time); }, time); |
| clearTimeOut() | 根據ID取消超時調用 | 超時調用ID | |||
| 循環 | setInterval() | 返回一個數值ID表示這個調用? | 執行函數或代碼、循環執行代碼的間隔時間(毫秒) | ||
| clearInterval() | 根據ID取消循環調用 | 循環調用ID | |||
| 新窗口 | 普通 | open() | 返回新打開窗口的引用 | 4個參數:目標URL,目標窗口名稱,特性字符串,是否取代歷史記錄中當前加載頁面的Boolean值 | 通常只需傳遞第一個參數,最后一個參數只在不打開新窗口的情況下使用。 如果傳遞了第二個參數,而且該參數是已有窗口或框架的名稱,那么就會在相應的窗口或框架中加載目標URL,如果是一個不存在的名稱,就會創建一個新窗口。第二個參數也可以是下面的特殊值:_self、_parent、_top、_blank。 |
說明:
A、表示窗口位置的屬性有screenLeft、screenTop、screenX、screenY、表示窗口大小的屬性有innerWidth、innerHeight、outerWidth、outerHeight,但是它們的具體含義和不同的瀏覽器密切相關,在上表中沒有列入。這些屬性的差異性給窗口控制的兼容性造成了非常大的困擾,不過好在現在已經有很多成熟的JS框架,在處理瀏覽器差異性建議使用這些JS框架。
B、moveTo()、moveBy()、resizeTo()、resizeBy()四個方法不適用于框架,只適用于最外層的window對象,而且這些方法可能會被瀏覽器禁用(在Opera和IE7+中默認就是禁用的)。
C、window.open()方法中的第三個參數為特性字符串,是一個逗號分隔的設置字符串,用來表示在新窗口中都顯示哪些特性,整個特性字符串不允許出現空格,特性和特性以逗號分隔,特性和特性值以等號(=)間隔。這些特性有(藍色的為默認值):
| 特性 | 取值范圍 | 說明 |
| fullscreen | yes|no | 表示瀏覽器窗口是否全屏,僅限IE |
| height | 數值(不能小于100) | 新窗口的高度 |
| width | 數值(不能小于100) | 新窗口的寬度 |
| left | 數值(不能是負值) | 新窗口的左坐標 |
| top | 數值(不能是負值) | 新窗口的上坐標 |
| toolbar | yes|no | 是否在瀏覽器窗口中顯示工具欄 |
| status | yes|no | 是否在瀏覽器窗口中顯示狀態欄 |
| scrollbars | yes|no | 如果內容在視口中顯示不下,是否顯示滾動條 |
| resizable | yes|no | 是否可以通過拖動瀏覽器窗口的邊框來改變其大小 |
| menubar | yes|no | 是否在瀏覽器窗口中顯示菜單欄 |
| location | yes|no | 是否在瀏覽器窗口中顯示地址欄,不同瀏覽器默認值不同,如果設置為no,地址欄可能會隱藏,也可能會被禁用 |
D、window.open()方法返回新創建窗口的一個引用,可以利用這個引用來操作新窗口,新窗口對象中有一個opener屬性指向原窗口。
//創建新窗口,返回這個新窗口對象的引用,如果代碼是在新打開窗口的頁面,則可以直接通過window訪問 var openWin = window.open("http://www.cnblogs.com/linjisong","cnblogs-lin","height=400,width=320,resizable=yes"); openWin.resizeTo(800,600);//重新定義大小 openWin.moveTo(100,100);//移動位置 console.info(openWin.opener === window);//true,新窗口對象中有一個opener屬性指向原窗口 openWin.close();//關閉新窗口 console.info(openWin.closed);//true,關閉之后可以訪問關閉狀態在使用window.open()方法時,出于安全性考慮,很多瀏覽器會有一些限制,比如Firefox強制顯示地址欄等,在實際開發過程中,需要根據目標瀏覽器來測試這些限制并采取相應的措施。
E、在IE中,除了window.open()之外,還可以通過window.showModelDialog()來彈出一個窗口,通常稱之為“模態窗口”,這種窗口會獨占系統資源,用戶只有在關閉它之后才能繼續其它的操作。由于模態窗口不是兼容所有瀏覽器,這里不再展開,有興趣的朋友可以找相應的資料了解一下。
二、history對象
history對象保存著從窗口被打開起的歷史記錄,每個瀏覽器窗口、標簽頁、框架都有自己的history對象。history對象的主要屬性和方法有:
| 屬性/方法 | 例子 | 說明 |
| length | if(history.length == 0)?//第一個頁面 | 歷史記錄的數量 |
| go() | history.go(-1); history.go(0); history.go(2); history.go('linjisong'); | 負數表示向后跳轉 0表示刷新當前頁面 正數表示向前跳轉 字符串參數,表示跳轉到歷史記錄中包含該字符串的最近一個位置(可能前進,也可能后退) |
| back() | history.back();相當于history.go(-1); | 后退一頁,可模仿瀏覽器“后退”按鈕 |
| forward() | history.forward();相當于history.go(1); | 前進一頁,可模仿瀏覽器“前進”按鈕 |
三、location對象
location對象提供了與當前窗口中加載的文檔有關的信息以及一些導航功能,它既是window對象的屬性,同時也是document對象的屬性,它的主要屬性和方法有:
| 屬性/方法 | 例子 | 說明 |
| hash | "#contents" | 返回URL中的hash(#號后跟零或多個字符),如果URL中不包括散列,返回空字符串 |
| host | "www.wrox.com:80" | 返回服務器名稱和端口號(如果有) |
| hostname | "www.wrox.com" | 返回不帶端口號的服務器名稱 |
| href | "http://www.wrox.com" | 返回當前加載頁面的完整URL,location對象的toString()方法也返回這個值 |
| pathname | "/WileyCDA" | 返回URL中的目錄和文件名 |
| port | "8080" | 返回URL中指定的端口號,如果不含端口號,返回空字符串 |
| protocol | "http:" | 反應頁面使用的協議,通常是http:或https: |
| search | "?q=javascript" | 返回URL的查詢字符串,這個字符串以問號開頭 |
| assign() | location.assign(URL) | 立即打開新URL并在瀏覽器歷史中生成一條記錄,相當于直接設置location.href值,也可以修改location對象的其它屬性來重新加載 |
| replace() | location.replace(URL) | 打開新URL,但是不會生成歷史記錄,使用replace()之后,用戶不能通過“后退”回到前一個頁面 |
| reload() | location.reload([true]) | 重新加載當前頁面,不傳遞參數時會以最有效方式加載(可能從緩存中加載),傳入true時,則強制從瀏覽器重新加載 |
說明:location.search返回的是包括所有參數的字符串,可以通過下面的方法將這個字符串轉換為一個參數對象(原書第207頁):
function getQueryStringArgs(){var qs = (location.search.length > 0 ? location.search.substring(1) : ""),//去掉查詢字符串前面的問號args = {},items = qs.length ? qs.split("&") : [],//將參數以&分隔item = null,name = null,value = null,i = 0,len = items.length;for (i=0; i < len; i++){//循環處理,將每一個參數的名稱和值加入到參數對象中item = items[i].split("=");name = decodeURIComponent(item[0]);value = decodeURIComponent(item[1]);if (name.length){args[name] = value;}}return args;}var args = getQueryStringArgs();//假定查詢字符串返回?q=javascript&num=10 console.info(args["q"]); //"javascript"console.info(args["num"]); //"10"注意:該方法對于查詢字符串中同一個參數多個值的情況(類似?val=1&val=2)處理會有問題。
四、navigator對象
navigator對象用來描述瀏覽器本身,包括瀏覽器的名稱、版本、語言、系統平臺、用戶特性字符串等信息,但是各個瀏覽器及瀏覽器的不同版本之間對這個對象的實現也不盡相同。
在非IE瀏覽器中,可以使用navigator對象的plugins屬性來檢測插件的安裝情況:
function hasPlugin(name){name = name.toLowerCase();for (var i=0; i < navigator.mimeTypes.length; i++){if (navigator.mimeTypes[i].name.toLowerCase().indexOf(name) > -1){return true;}}return false; }也可以使用navigator對象的userAgent屬性(用戶代理字符串)來檢測客戶端對某種功能的支持情況。不過在檢測瀏覽器是否支持某種功能的時候,首先應使用特性檢測來判斷,特性檢測的目標不是判斷是什么瀏覽器,而是判斷瀏覽器是否支持某種能力,比如在IE早期版本中不存在document.getElementById(),而是使用非標準的document.all來獲取DOM元素,就可以使用如下代碼:
function getElement(id){if(document.getElementById){//特性檢測,如果支持,優先使用document.getElementById()return document.getElementById(id); }else{return document.all[id];} }有時候雖然支持某種特性,但是這種特性并不是想要的功能,這種情況下,可以對特性進一步做檢測,比如通過下面的代碼進一步判斷支持的特性是否為函數:
typeof document.createElement === 'function'當然,特性檢測并不總是能湊效,這時不得已就只好通過navigator對象來對檢測了,因為userAgent是在瀏覽器發展過程中逐步演變而來的,因此使用這種檢測技術需要了解各種瀏覽器的發展歷史,這里就不具體展開了,建議就是使用成熟的JS庫來代替直接使用navigator.userAgent進行檢測。
五、screen對象
screen對象用來表明客戶端的能力,包括瀏覽器窗口外部的顯示器的信息,如像素寬度和高度等,每個瀏覽器中的screen對象都包含著各不相同的屬性,其中五大瀏覽器都支持的屬性有:
- height:屏幕的像素高度
- width:屏幕的像素寬度
- availHeight:屏幕的像素高度減系統部件高度之后的值(只讀)
- availWidth:屏幕的像素寬度減系統部件寬度之后的值(只讀)
screen對象經常集中出現在測定客戶端能力的站點跟蹤工具中,有時候也可能會用到其中的信息來調整瀏覽器窗口的大小,使其占據屏幕的可用空間,比如:
window.resizeTo(screen.availWidth, screen.availHeight); 《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的浏览器对象模型BOM的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 使用DOM操纵HTML文档几点粗浅认识
- 下一篇: DOM 基本方法