Level 0 DOM 簡介


在瀏覽器開始支援 JavaScript 時,存在一組物件提供有限的功能,在當時 Netscape Navigator 與 Internet Explorer 大戰的年代,兩個瀏覽器在這組物件上有些交集的部份,這些交集的部份被留存到現在,並在一些主流的瀏覽器中仍有支援。這組物件稱為瀏覽器物件模型(Browser Object Model)或非正式地稱為 Level 0 DOM,因為它在 DOM(Document Object Model)標準化前就已存在,而不是真有有文件規範 Level 0 DOM。

這組物件從全域物件 window 開始,具有以下的特性階層關係:

window|
      |navigator
      |location
      |frames
      |screen
      |history
      |document
              |forms
              |links
              |anchors
              |images
              |all
              |cookie

這些物件在一般 JavaScript 的書中都有介紹,使用上雖然不難,但有些會有跨瀏覽器的問題(以下列的參考鏈結,大致有標出適用哪些瀏覽器),以下僅作每個物件的簡介。

window 物件代表瀏覽器視窗本身,為 Window 的實例,是 JavaScript 以瀏覽器為客戶端時的頂層物件,其中像是 alertconfirmpromptsetTimeoutclearTimeoutsetIntervalclearInterval 等函式,都是以 window 作為名稱空間物件的函式。

window 本身也擁有一些控制視窗的方法,例如 openmoveToscrollscrollTo 等。可以在〈Window Object〉 查詢這些函式或方法的使用方式。

window.navigator 代表了瀏覽器,為 Navigator 的實例,可以從這個物件上取得瀏覽器本身的資訊,通常是為了進行所謂瀏覽器偵測才會使用這個物件,不過這個物件取得的資訊並非完全可靠,因為有的瀏覽器提供有選項或者有工具可變造這些資訊。你可以在〈Navigator Object〉查詢這個物件上有哪些資訊可以取得。

window.location 代表了視窗目前所顯示頁面的 URL,是 Location 的實例,可以從這個物件上取得目前頁面的 URL 相關資訊,也有 reloadreplace 方法,可以重新載入頁面或取代頁面。可在〈Location Object〉 查詢這個物件的相關內容。也有個 window.document.location,與 window.location 是同一個物件。

window.frames 是目前視窗中擁有的框架,以類陣列的 HTMLCollection 物件組織這些物件,索引位置是框架在視窗中出現的順序,如果框架有設定 idname 屬性,也可以使用 [] 搭配名稱來取得框架,每個取得的框架都是 Window 的實例。在〈安全限制〉 中就有個例子使用了 window.frames

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
</head>
<body>

    <iframe id="page" name="page" src="https://openhome.cc"></iframe>
    <span id="console"></span>

<script type="text/javascript">
    window.onload = function() {    
        alert(window.frames['page'].document.body.innerHTML);
    };
</script>  

</body>
</html>

window.screen 物件包括了目前視窗所關聯的螢幕資訊,像是寬、高、顏色深度等,為 Screen 的實例,可以在〈Screen Object〉查詢各個特性。

window.history 則包括了瀏覽器瀏覽歷史,為 History 實例,基於安全與隱私,你無法取得瀏覽歷史,但可以有 backforwardgo 等方法,指定前進、後退至哪個歷史頁面,像是回到上一面、下一頁的功能,想使用 JavaScript 控制,就可以用這個物件,可查詢〈History Object〉了解細節。

window.documentDocument 的實例,代表整份 HTML 文件,這個物件上提供一組群集(Collection)物件,它們都是 HTMLCollection 的實例,這些群集物件都有個特徵,本身可以用 [] 搭配索引數字來存取,如果相對應的標籤有 idname 屬性,也可以使用 [] 搭配名稱來存取,或是搭配點算子與名稱來存取(先前介紹的 window.frames 也有這種特徵)。

HTMLCollection 規範的是使用 item 方法搭配索引來取得元素,或使用 namedItem 方法搭配 idname 屬性來取得元素,不過在 JavaScript 實作中,可以且通常使用 [] 搭配索引或名稱來取得元素。)

舉個來說,如果有個網頁如下:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
</head>
<body>

    <form name="login">
        User: <input type="text" name="user" value="guest"><br>
        Password: <input type="password" name="passwd" value="guest">
        <button type="submit">Submit<button/>
    </form>

</body>
</html>

想要取得文件中 namelogin 的表單,有幾種方式:

document.forms[0]         // 文件中第一個表單,索引為 0
document.forms['login']
document.forms.login

formslinksanchorsimages 等,都可以用這種方式來取得。

在透過 document.forms 取得某個表單元素之後,如果想取得其下的子元素,可以使用 elements 來取得,一樣可以使用索引或 name 搭配 [] 來取得,也可以透過 . 運算子來取得。例如,想取得 nameuser 的輸入文字框,可以如下:

document.forms['login'].elements[0]      // 表單中第一個元素
document.forms['login'].elements['user']
document.forms['login'].elements.user 

表單比較特別,如果你的表單有 name 屬性,而當中的元素也有 name 屬性,則可以有個很方便的存取方式。例如若要取得 login 表單的 user 欄位,則可以如下:

document.login.user

由於輸入欄位有個 value 屬性,所以要取得欄位值就是:

document.login.user.value

只要你取得標籤元素,標籤上的某個屬性,基本上可以在物件上使用相對應的特性來取得,除了一些保留字之外,例如 class 屬性要用 className 特性名稱來取得,因為 class 是保留字,而 <label>for 屬性要用 htmlFor 特性來取得。

超鏈結與錨點都是使用 <a> 來定義,差別在於超鏈結使用 href 屬性,而錨點使用 name 屬性, document.linksdocument.anchors 則分別表示超鏈結與錨點元素。

documents.images 則表示了文件中的所有 <img> 元素。

document.all 代表文件中所有元素,是早期存取文件中所有元素的方式。例如,若文件中某個元素具有 name 屬性值為 'element1',則可以透過這種方式來取得:

document.all['element1']

在 DOM 標準化之後,這種寫法的作用已經被 document.getElementsByName 等方法取代了。

documentcookie 則允許設定與讀取 cookie,設定方式是字串,形式為 name=value,每個 name/value 間以分號區隔,取得的也是字串,你必須自行剖析 name/value 對。可以參考〈Cookie〉稍微了解一下 Cookie 的原理。

基於安全性,被標示了 HttpOnly 屬性的 Cookie,無法使用 JavaScript 來讀取。