JS之BOM

ECMAScript 是 JavaScript 的核心,但若是要在 Web 中使用 JavaScript,那麼 BOM(瀏覽器對象模型)則無疑纔是真正的核心。BOM 提供了不少對象,用於訪問瀏覽器的功能,這些功能與任何網頁內容無關。多年來,缺乏事實上的規範致使 BOM 有不少問題,由於瀏覽器提供商會按照各自的想法隨意去擴展它。W3C 爲了把瀏覽器中 JavaScript 最基本的部分標準化,已經將 BOM 的主要方面歸入了 HTML5 的規範中。javascript

window 對象

BOM 的核心對象是 window ,它表示瀏覽器的一個實例。在瀏覽器中, window 對象有雙重角色,它既是經過 JavaScript 訪問瀏覽器窗口的一個接口,又是 ECMAScript 規定的 Global 對象。這意味着在網頁中定義的任何一個對象、變量和函數,都以 window 做爲其 Global 對象,所以有權訪問 isNaN() 、 isFinite() 、 parseInt() 、 parseFloat() 等方法。html

全局做用域

因爲 window 對象同時扮演着 ECMAScript 中 Global 對象的角色,所以全部在全局做用域中聲明的變量、函數都會變成 window 對象的屬性和方法。來看下面的例子。java

var age = 29; function sayAge(){ console.log(this.age); } console.log(window.age); // 29 sayAge(); // 29 window.sayAge(); // 29

拋開全局變量會成爲 window 對象的屬性不談,定義全局變量與在 window 對象上直接定義屬性仍是有一點差異:全局變量不能經過 delete 運算符刪除,而直接在 window 對象上的定義的屬性能夠。例如:編程

var age = 29; window.color = "red"; // 在 IE < 9 時拋出錯誤,在其餘全部瀏覽器中都返回 false delete window.age; // 在 IE < 9 時拋出錯誤,在其餘全部瀏覽器中都返回 true delete window.color; // return true console.log(window.age); // 29 console.log(window.color); // undefined

使用 var 語句添加的 window 屬性有一個名爲 Configurable 的特性,這個特性的值被默認設置爲 false ,所以這樣定義的屬性不能夠經過 delete 運算符刪除。IE8 及更早版本在遇到使用 delete 刪除 window 屬性的語句時,無論該屬性最初是如何建立的,都會拋出錯誤,以示警告。IE9 及更高版本不會拋出錯誤。segmentfault

另外,還要記住一件事:嘗試訪問未聲明的變量會拋出錯誤,可是經過查詢 window 對象,能夠知道某個可能未聲明的變量是否存在。例如:瀏覽器

// 這裏會拋出錯誤,由於 oldValue 未定義 var newValue = oldValue; // 這裏不會拋出錯誤,由於這是一次屬性查詢 // newValue 的值是 undefined var newValue = window.oldValue;

窗口關係及框架

若是頁面中包含框架,則每一個框架都擁有本身的 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>

對這個例子而言,能夠經過 window.frames[0] 或者 window.frames["topFrame"] 來引用上方的框架。不過最好使用 top 而非 window 來引用這些框架(例如 top.frames[0] ),由於 top 對象始終指向最高(最外)層的框架,也就是瀏覽器窗口。使用它能夠確保在一個框架中正確地訪問另外一個框架。由於對於在一個框架中編寫的任何代碼來講,其中的 window 對象指向的都是那個框架的特定實例,而非最高層的框架。安全

與 top 相對的另外一個 window 對象是 parent 。顧名思義, parent (父)對象始終指向當前框架的直接上層框架。在某些狀況下, parent 有可能等於 top ;但在沒有框架的狀況下, parent 必定等於 top (此時它們都等於 window )。服務器

與框架有關的最後一個對象是 self ,它始終指向 window ;實際上, self 和 window 對象能夠互換使用。引入 self 對象的目的只是爲了與 top 和 parent 對象對應起來,所以它不格外包含其餘值。網絡

全部這些對象都是 window 對象的屬性,能夠經過 window.parent 、 window.top 等形式來訪問。同時,這也意味着能夠將不一樣層次的 window 對象連綴起來,例如 window.parent.parent.frames[0] 。

在使用框架的狀況下,瀏覽器中會存在多個 Global 對象。在每一個框架中定義的全局變量會自動成爲框架中 window 對象的屬性。因爲每一個 window 對象都包含原生類型的構造函數,所以每一個框架都有一套本身的構造函數,這些構造函數一一對應,但並不相等。例如, top.Object 並不等於 top.frames[0].Object 。這個問題會影響到對跨框架傳遞的對象使用 instanceof 運算符。

導航和打開窗口

使用 window.open() 方法既能夠導航到一個特定的 URL,也能夠打開一個新的瀏覽器窗口。這個方法能夠接收4個參數:要加載的URL、窗口目標、一個特性字符串以及一個表示新頁面是否取代瀏覽器歷史記錄中當前加載頁面的布爾值。一般只須傳遞第一個參數,最後一個參數只在不打開新窗口的狀況下使用。

若是爲 window.open() 傳遞了第二個參數,並且該參數是已有窗口或框架的名稱,那麼就會在具備該名稱的窗口或框架中加載第一個參數指定的 URL。看下面的例子。

// 等同於 <a href="http://shijiajie.com" target="newWindow"></a> window.open("http://shijiajie.com/", "newWindow");

彈出窗口

若是給 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

這行代碼會打開一個新的能夠調整大小的窗口,窗口初始大小爲400×400像素,而且距屏幕上沿和左邊各10像素。

window.open("http://shijiajie.com/","newWindow", "height=400,width=400,top=10,left=10,resizable=yes");

window.open() 方法會返回一個指向新窗口的引用。引用的對象與其餘 window 對象大體類似,但咱們能夠對其進行更多控制。例如,有些瀏覽器在默認狀況下可能不容許咱們針對主瀏覽器窗口調整大小或移動位置,但卻容許咱們針對經過window.open()建立的窗口調整大小或移動位置。經過這個返回的對象,能夠像操做其餘窗口同樣操做新打開的窗口,以下所示。

var win = window.open("http://shijiajie.com/","newWindow", "height=400,width=400,top=10,left=10,resizable=yes"); // 調整大小 win.resizeTo(500,500); // 移動位置 win.moveTo(100,100); // 關閉窗口 win.close();

可是, close() 方法僅適用於經過 window.open() 打開的彈出窗口。對於瀏覽器的主窗口,若是沒有獲得用戶的容許是不能關閉它的。

新建立的 window 對象有一個 opener 屬性,其中保存着打開它的原始窗口對象。這個屬性只在彈出窗口中的最外層 window 對象(top)中有定義,並且指向調用 window.open() 的窗口或框架。例如:

var win = window.open("http://shijiajie.com/","newWindow", "height=400,width=400,top=10,left=10,resizable=yes"); console.log(win.opener === window); // true

雖然彈出窗口中有一個指針指向打開它的原始窗口,但原始窗口中並無這樣的指針指向彈出窗口。窗口並不跟蹤記錄它們打開的彈出窗口,所以咱們只能在必要的時候本身來手動實現跟蹤。

彈出窗口屏蔽程序

曾經有一段時間,廣告商在網上使用彈出窗口達到了肆無忌憚的程度。他們常常把彈出窗口打扮成系統對話框的模樣,引誘用戶去點擊其中的廣告。因爲看起來像是系統對話框,通常用戶很難分辨是真是假。爲了解決這個問題,大多數瀏覽器內置有彈出窗口屏蔽程序,將絕大多數用戶不想看到彈出窗口屏蔽掉。

因而,在彈出窗口被屏蔽時,就應該考慮兩種可能性。若是是瀏覽器內置的屏蔽程序阻止的彈出窗口,那麼 window.open() 極可能會返回 null ,若是是瀏覽器擴展或其餘程序阻止的彈出窗口,那麼 window.open() 一般會拋出一個錯誤。所以,要想準確地檢測出彈出窗口是否被屏蔽,必須在檢測返回值的同時,將對 window.open() 的調用封裝在一個 try-catch 塊中,以下所示。

var blocked = false; try { var win = window.open("http://shijiajie.com", "_blank"); if (win == null){ blocked = true; } } catch (ex){ blocked = true; } if (blocked){ console.log("The popup was blocked!"); }

間歇調用和超時調用

JavaScript 是單線程語言,但它容許經過設置超時值和間歇時間值來調度代碼在特定的時刻執行。前者是在指定的時間事後執行代碼,然後者則是每隔指定的時間就執行一次代碼。

超時調用須要使用 window 對象的 setTimeout() 方法,它接受兩個參數:要執行的代碼和以毫秒錶示的時間(即在執行代碼前須要等待多少毫秒)。其中,第一個參數能夠是一個包含 JavaScript 代碼的字符串(就和在 eval() 函數中使用的字符串同樣),也能夠是一個函數。例如,下面對 setTimeout() 的兩次調用都會在一秒鐘後顯示一個警告框。

// 不建議傳遞字符串 setTimeout("console.log('Hello world!') ", 1000); // 推薦的調用方式 setTimeout(function() { console.log("Hello world!"); }, 1000);

雖然這兩種調用方式都沒有問題,但因爲傳遞字符串可能致使性能損失,所以不建議以字符串做爲第一個參數。

第二個參數是一個表示等待多長時間的毫秒數,但通過該時間後指定的代碼不必定會執行。JavaScript 是一個單線程序的解釋器,所以必定時間內只能執行一段代碼。爲了控制要執行的代碼,就有一個 JavaScript 任務隊列。這些任務會按照將它們添加到隊列的順序執行。 setTimeout() 的第二個參數告訴 JavaScript 再過多長時間把當前任務添加到隊列中。若是隊列是空的,那麼添加的代碼會當即執行;若是隊列不是空的,那麼它就要等前面的代碼執行完了之後再執行。

調用 setTimeout() 以後,該方法會返回一個數值 ID ,表示超時調用。這個超時調用 ID 是計劃執行代碼的惟一標識符,能夠經過它來取消超時調用。要取消還沒有執行的超時調用計劃,能夠調用 clearTimeout() 方法並將相應的超時調用 ID 做爲參數傳遞給它,以下所示。

// 設置超時調用 var timeoutId = setTimeout(function() { console.log("Hello world!"); }, 1000); // 注意:把它取消 clearTimeout(timeoutId);

只要是在指定的時間還沒有過去以前調用 clearTimeout() ,就能夠徹底取消超時調用。前面的代碼在設置超時調用以後立刻又調用了 clearTimeout() ,結果就跟什麼也沒有發生同樣。

間歇調用與超時調用相似,只不過它會按照指定的時間間隔重複執行代碼,直至間歇調用被取消或者頁面被卸載。設置間歇調用的方法是 setInterval() ,它接受的參數與 setTimeout() 相同:要執行的代碼(字符串或函數)和每次執行以前須要等待的毫秒數。下面來看一個例子。

// 不建議傳遞字符串 setInterval ("console.log('Hello world!') ", 10000); // 推薦的調用方式 setInterval (function() { console.log("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); console.log("Done"); } } intervalId = setInterval(incrementNumber, 500);

在這個例子中,變量num每半秒鐘遞增一次,當遞增到最大值時就會取消先前設定的間歇調用。這個模式也可使用超時調用來實現,以下所示。

var num = 0; var max = 10; function incrementNumber() { num++; // 若是執行次數未達到max設定的值,則設置另外一次超時調用 if (num < max) { setTimeout(incrementNumber, 500); } else { console.log("Done"); } } setTimeout(incrementNumber, 500);

可見,在使用超時調用時,沒有必要跟蹤超時調用 ID ,由於每次執行代碼以後,若是再也不設置另外一次超時調用,調用就會自行中止。通常認爲,使用超時調用來模擬間歇調用的是一種最佳模式。在開發環境下,不多使用真正的間歇調用,緣由是後一個間歇調用可能會在前一個間歇調用結束以前啓動。而像前面示例中那樣使用超時調用,則徹底能夠避免這一點。因此,最好不要使用間歇調用。

系統對話框

瀏覽器經過 alert() 、 confirm() 和 prompt() 方法能夠調用系統對話框向用戶顯示消息。系統對話框與在瀏覽器中顯示的網頁沒有關係,也不包含 HTML。它們的外觀由操做系統及(或)瀏覽器設置決定,而不是由 CSS 決定。此外,經過這幾個方法打開的對話框都是同步和模態的。也就是說,顯示這些對話框的時候代碼會中止執行,而關掉這些對話框後代碼又會恢復執行。

第一種對話框是調用 alert() 方法生成的。它向用戶顯示一個系統對話框,其中包含指定的文本和一個 OK(「肯定」)按鈕。一般使用 alert() 生成的「警告」對話框向用戶顯示一些他們沒法控制的消息,例如錯誤消息。而用戶只能在看完消息後關閉對話框。

第二種對話框是調用 confirm() 方法生成的。從向用戶顯示消息的方面來看,這種「確認」對話框很像是一個「警告」對話框。但兩者的主要區別在於「確認」對話框除了顯示OK按鈕外,還會顯示一個 Cancel(「取消」)按鈕,兩個按鈕可讓用戶決定是否執行給定的操做。

爲了肯定用戶是單擊了OK仍是Cancel,能夠檢查 confirm() 方法返回的布爾值: true 表示單擊了OK, false 表示單擊了Cancel或單擊了右上角的 X 按鈕。確認對話框的典型用法以下。

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() 方法生成的,這是一個「提示」框,用於提示用戶輸入一些文本。提示框中除了顯示 OK 和 Cancel 按鈕以外,還會顯示一個文本輸入域,以供用戶在其中輸入內容。 prompt() 方法接受兩個參數:要顯示給用戶的文本提示和文本輸入域的默認值(能夠是一個空字符串)。

若是用戶單擊了 OK 按鈕,則 promp() 返回文本輸入域的值;若是用戶單擊了 Cancel 或沒有單擊 OK 而是經過其餘方式關閉了對話框,則該方法返回 null 。下面是一個例子。

var result = prompt("What is your name? ", ""); if (result !== null) { alert("Welcome, " + result); }

綜上所述,這些系統對話框很適合向用戶顯示消息並請用戶做出決定。因爲不涉及 HTML、CSS 或 JavaScript,所以它們是加強 Web 應用程序的一種便捷方式。

location 對象

location 對象提供了與當前窗口中加載的文檔有關的信息,還提供了一些導航功能。事實上, location 對象是很特別的一個對象,由於它既是 window 對象的屬性,也是 document 對象的屬性;換句話說, window.location 和 document.location 引用的是同一個對象。 location 對象的用處不僅表如今它保存着當前文檔的信息,還表如今它將 URL 解析爲獨立的片斷,讓開發人員能夠經過不一樣的屬性訪問這些片斷。下表列出了 location 對象的全部屬性。

屬性名 例子 說明
hash "#contents" 返回 URL 中的 hash(#號後跟零或多個字符),若是 URL 中不包含散列,則返回空字符串
host "shijiajie.com:80" 返回服務器名稱和端口號(若是有)
hostname "shijiajie.com" 返回不帶端口號的服務器名稱
href "http:/shijiajie.com" 返回當前加載頁面的完整URL。而 location 對象的 toString() 方法也返回這個值
pathname "/WileyCDA/" 返回URL中的目錄和(或)文件名
port "8080" 返回 URL 中指定的端口號。若是 URL 中不包含端口號,則這個屬性返回空字符串
protocol "http:" 返回頁面使用的協議。一般是 http: 或 https:
search "?q=javascript" 返回URL的查詢字符串。這個字符串以問號開頭

查詢字符串參數

雖然經過上面的屬性能夠訪問到 location 對象的大多數信息,但其中訪問URL包含的查詢字符串的屬性並不方便。儘管 location.search 返回從問號到 URL 末尾的全部內容,但卻沒有辦法逐個訪問其中的每一個查詢字符串參數。爲此,能夠像下面這樣建立一個函數,用以解析查詢字符串,而後返回包含全部參數的一個對象:

/* * 這個函數用來解析來自URL的查詢串中的name=value參數對 * 它將name=value對存儲在一個對象的屬性中,並返回該對象 * 這樣來使用它 * * var args = urlArgs(); // 從URL中解析參數 * var q = args.q || ""; // 若是參數定義了的話就使用參數;不然使用一個默認值 * var n = args.n ? parseInt(args.n) : 10; */ function urlArgs() { var args = {}; // 定義一個空對象 var query = location.search.substring(1); // 查找到查詢串,並去掉'? ' var pairs = query.split("&"); // 根據"&"符號將查詢字符串分隔開 for (var i = 0; i < pairs.length; i++) { // 對於每一個片斷 var pos = pairs[i].indexOf('='); // 查找"name=value" if (pos == -1) continue; // 若是沒有找到的話,就跳過 var name = pairs[i].substring(0, pos); // 提取name var value = pairs[i].substring(pos + 1); // 提取value value = decodeURIComponent(value); // 對value進行解碼 args[name] = value; // 存儲爲屬性 } return args; // 返回解析後的參數 }

位置操做

使用 location 對象能夠經過不少方式來改變瀏覽器的位置。首先,也是最經常使用的方式,就是使用 assign() 方法併爲其傳遞一個 URL,以下所示。

location.assign("http://shijiajie.com");

這樣,就能夠當即打開新URL並在瀏覽器的歷史記錄中生成一條記錄。若是是將 location.href 或 window.location 設置爲一個URL值,也會以該值調用 assign() 方法。例如,下列兩行代碼與顯式調用 assign() 方法的效果徹底同樣。

window.location = "http://shijiajie.com"; location.href = "http://shijiajie.com";

在這些改變瀏覽器位置的方法中,最經常使用的是設置 location.href 屬性。

另外,修改 location 對象的其餘屬性也能夠改變當前加載的頁面。下面的例子展現了經過將 hash 、 search 、 hostname 、 pathname 和 port 屬性設置爲新值來改變 URL。

// 假設初始 URL 爲 http://shijiajie.com/about/ location.href = "http://shijiajie.com/about/" // 將 URL 修改成 "http://shijiajie.com/about/#ds-thread" location.hash = "#ds-thread"; // 將 URL 修改成 "http://shijiajie.com/about/?args=123" location.search = "?args=123"; // 將 URL 修改成 "https://segmentfault.com/" location.hostname = "segmentfault.com"; // 將 URL 修改成 "http://segmentfault.com/u/stone0090/" location.pathname = "u/stone0090"; // 將 URL 修改成 "https://segmentfault.com:8080/" location.port = 8080;

當經過上述任何一種方式修改URL以後,瀏覽器的歷史記錄中就會生成一條新記錄,所以用戶經過單擊「後退」按鈕都會導航到前一個頁面。要禁用這種行爲,可使用 replace() 方法。這個方法只接受一個參數,即要導航到的 URL;結果雖然會致使瀏覽器位置改變,但不會在歷史記錄中生成新記錄。在調用 replace() 方法以後,用戶不能回到前一個頁面,來看下面的例子:

<!DOCTYPE html>
<html> <head> <title>You won't be able to get back here</title> </head> <body> <p>Enjoy this page for a second, because you won't be coming back here.</p> <script type="text/javascript"> setTimeout(function () { location.replace("http://shijiajie.com/"); }, 1000); </script> </body> </html>

若是將這個頁面加載到瀏覽器中,瀏覽器就會在1秒鐘後從新定向到 shijiajie.com 。而後,「後退」按鈕將處於禁用狀態,若是不從新輸入完整的 URL,則沒法返回示例頁面。

與位置有關的最後一個方法是 reload() ,做用是從新加載當前顯示的頁面。若是調用 reload() 時不傳遞任何參數,頁面就會以最有效的方式從新加載。也就是說,若是頁面自上次請求以來並無改變過,頁面就會從瀏覽器緩存中從新加載。若是要強制從服務器從新加載,則須要像下面這樣爲該方法傳遞參數 true 。

location.reload();        // 從新加載(有可能從緩存中加載) location.reload(true); // 從新加載(從服務器從新加載)

位於 reload() 調用以後的代碼可能會也可能不會執行,這要取決於網絡延遲或系統資源等因素。爲此,最好將 reload() 放在代碼的最後一行。

history 對象

history 對象保存着用戶上網的歷史記錄,從窗口被打開的那一刻算起。由於 history 是 window 對象的屬性,所以每一個瀏覽器窗口、每一個標籤頁乃至每一個框架,都有本身的 history 對象與特定的 window 對象關聯。出於安全方面的考慮,開發人員沒法得知用戶瀏覽過的 URL。不過,藉由用戶訪問過的頁面列表,一樣能夠在不知道實際 URL 的狀況下實現後退和前進。

使用 go() 方法能夠在用戶的歷史記錄中任意跳轉,能夠向後也能夠向前。這個方法接受一個參數,表示向後或向前跳轉的頁面數的一個整數值。負數表示向後跳轉(相似於單擊瀏覽器的「後退」按鈕),正數表示向前跳轉(相似於單擊瀏覽器的「前進」按鈕)。來看下面的例子。

// 後退一頁 history.go(-1); // 前進一頁 history.go(1); // 前進兩頁 history.go(2);

也能夠給 go() 方法傳遞一個字符串參數,此時瀏覽器會跳轉到歷史記錄中包含該字符串的第一個位置——可能後退,也可能前進,具體要看哪一個位置最近。若是歷史記錄中不包含該字符串,那麼這個方法什麼也不作,例如:

// 跳轉到最近的 shijiajie.com 頁面 history.go("shijiajie.com");

另外,還可使用兩個簡寫方法 back() 和 forward() 來代替 go() 。顧名思義,這兩個方法能夠模仿瀏覽器的「後退」和「前進」按鈕。

// 後退一頁 history.back(); // 前進一頁 history.forward();

除了上述幾個方法外, history 對象還有一個 length 屬性,保存着歷史記錄的數量。這個數量包括全部歷史記錄,即全部向後和向前的記錄。對於加載到窗口、標籤頁或框架中的第一個頁面而言, history.length 等於0。經過像下面這樣測試該屬性的值,能夠肯定用戶是否一開始就打開了你的頁面。

if (history.length == 0){ //這應該是用戶打開窗口後的第一個頁面 }

雖然 history 並不經常使用,但在建立自定義的「後退」和「前進」按鈕,以及檢測當前頁面是否是用戶歷史記錄中的第一個頁面時,仍是必須使用它。

小結

BOM(瀏覽器對象模型)以 window 對象爲依託,表示瀏覽器窗口以及頁面可見區域。同時, window 對象仍是 ECMAScript 中的 Global 對象,於是全部全局變量和函數都是它的屬性,且全部原生的構造函數及其餘函數也都存在於它的命名空間下。本章討論了下列 BOM 的組成部分。

  • 在使用框架時,每一個框架都有本身的 window 對象以及全部原生構造函數及其餘函數的副本。每一個框架都保存在 frames 集合中,能夠經過位置或經過名稱來訪問。
  • 有一些窗口指針,能夠用來引用其餘框架,包括父框架。
  • top 對象始終指向最外圍的框架,也就是整個瀏覽器窗口。
  • parent 對象表示包含當前框架的框架,而 self 對象則回指 window 。
  • 使用 location 對象能夠經過編程方式來訪問瀏覽器的導航系統。設置相應的屬性,能夠逐段或總體性地修改瀏覽器的 URL。
  • 調用 replace() 方法能夠導航到一個新 URL,同時該 URL 會替換瀏覽器歷史記錄中當前顯示的頁面。
  • navigator 對象提供了與瀏覽器有關的信息。到底提供哪些信息,很大程度上取決於用戶的瀏覽器;不過,也有一些公共的屬性(如 userAgent )存在於全部瀏覽器中。

BOM中還有兩個對象: screen 和 history ,但它們的功能有限。 screen 對象中保存着與客戶端顯示器有關的信息,這些信息通常只用於站點分析。 history 對象爲訪問瀏覽器的歷史記錄開了一個小縫隙,開發人員能夠據此判斷歷史記錄的數量,也能夠在歷史記錄中向後或向前導航到任意頁面。

關卡

// 挑戰一 setTimeout(function () { console.log("1"); }, 0) console.log("2"); // ???
// 挑戰二 for (var i = 0;i<5;i++) { setTimeout(function () { console.log(i); // ??? }, 0) };
// 挑戰三 var a = 1; var obj = { a : 2, b : function(){ setTimeout(function () { console.log(this.a); }, 0) } } obj.b(); // ???
// 挑戰四 var a = 1; var obj = { a : 2, b : function(){ setTimeout(function () { console.log(this.a); }.call(this), 0); } } obj.b(); // ???

 

 

來自:http://www.jianshu.com/p/0acba06fd13e

相關文章
相關標籤/搜索