摘要:對象的核心對象是,它表示瀏覽器的一個(gè)實(shí)例。及更高版本不會(huì)拋出錯(cuò)誤。與框架有關(guān)的最后一個(gè)對象是,它始終指向?qū)嶋H上,和對象可以互換使用。設(shè)置值說明或表示瀏覽器窗口是否最大化。僅限數(shù)值表示新窗口的高度。
ECMAScript 是 JavaScript 的核心,但如果要在 Web 中使用 JavaScript,那么 BOM(瀏覽器對象模型)則無疑才是真正的核心。BOM 提供了很多對象,用于訪問瀏覽器的功能,這些功能與任何網(wǎng)頁內(nèi)容無關(guān)。多年來,缺少事實(shí)上的規(guī)范導(dǎo)致 BOM 有很多問題,因?yàn)闉g覽器提供商會(huì)按照各自的想法隨意去擴(kuò)展它。W3C 為了把瀏覽器中 JavaScript 最基本的部分標(biāo)準(zhǔn)化,已經(jīng)將 BOM 的主要方面納入了 HTML5 的規(guī)范中。
window 對象BOM 的核心對象是 window,它表示瀏覽器的一個(gè)實(shí)例。在瀏覽器中,window 對象有雙重角色,它既是通過 JavaScript 訪問瀏覽器窗口的一個(gè)接口,又是 ECMAScript 規(guī)定的 Global 對象。這意味著在網(wǎng)頁中定義的任何一個(gè)對象、變量和函數(shù),都以 window 作為其 Global 對象,因此有權(quán)訪問 isNaN()、isFinite()、parseInt()、parseFloat() 等方法。
全局作用域由于 window 對象同時(shí)扮演著 ECMAScript 中 Global 對象的角色,因此所有在全局作用域中聲明的變量、函數(shù)都會(huì)變成 window 對象的屬性和方法。來看下面的例子。
var age = 29; function sayAge(){ console.log(this.age); } console.log(window.age); // 29 sayAge(); // 29 window.sayAge(); // 29
拋開全局變量會(huì)成為 window 對象的屬性不談,定義全局變量與在 window 對象上直接定義屬性還是有一點(diǎn)差別:全局變量不能通過 delete 運(yùn)算符刪除,而直接在 window 對象上的定義的屬性可以。例如:
var age = 29; window.color = "red"; // 在 IE < 9 時(shí)拋出錯(cuò)誤,在其他所有瀏覽器中都返回 false delete window.age; // 在 IE < 9 時(shí)拋出錯(cuò)誤,在其他所有瀏覽器中都返回 true delete window.color; // return true console.log(window.age); // 29 console.log(window.color); // undefined
使用 var 語句添加的 window 屬性有一個(gè)名為 Configurable 的特性,這個(gè)特性的值被默認(rèn)設(shè)置為 false,因此這樣定義的屬性不可以通過 delete 運(yùn)算符刪除。IE8 及更早版本在遇到使用 delete 刪除 window 屬性的語句時(shí),不管該屬性最初是如何創(chuàng)建的,都會(huì)拋出錯(cuò)誤,以示警告。IE9 及更高版本不會(huì)拋出錯(cuò)誤。
另外,還要記住一件事:嘗試訪問未聲明的變量會(huì)拋出錯(cuò)誤,但是通過查詢 window 對象,可以知道某個(gè)可能未聲明的變量是否存在。例如:
// 這里會(huì)拋出錯(cuò)誤,因?yàn)?oldValue 未定義 var newValue = oldValue; // 這里不會(huì)拋出錯(cuò)誤,因?yàn)檫@是一次屬性查詢 // newValue 的值是 undefined var newValue = window.oldValue;窗口關(guān)系及框架
如果頁面中包含框架,則每個(gè)框架都擁有自己的 window 對象,并且保存在 frames 集合中。在 frames 集合中,可以通過數(shù)值索引(從0開始,從左至右,從上到下)或者框架名稱來訪問相應(yīng)的 window 對象。每個(gè) window 對象都有一個(gè) name 屬性,其中包含框架的名稱。下面是一個(gè)包含框架的頁面:
Frameset Example
對這個(gè)例子而言,可以通過 window.frames[0] 或者 window.frames["topFrame"] 來引用上方的框架。不過最好使用 top 而非 window 來引用這些框架(例如 top.frames[0]),因?yàn)?top 對象始終指向最高(最外)層的框架,也就是瀏覽器窗口。使用它可以確保在一個(gè)框架中正確地訪問另一個(gè)框架。因?yàn)閷τ谠谝粋€(gè)框架中編寫的任何代碼來說,其中的 window 對象指向的都是那個(gè)框架的特定實(shí)例,而非最高層的框架。
與 top 相對的另一個(gè) window 對象是 parent。顧名思義,parent(父)對象始終指向當(dāng)前框架的直接上層框架。在某些情況下,parent 有可能等于 top;但在沒有框架的情況下,parent 一定等于 top(此時(shí)它們都等于 window)。
與框架有關(guān)的最后一個(gè)對象是 self,它始終指向 window;實(shí)際上,self 和 window 對象可以互換使用。引入 self 對象的目的只是為了與 top 和 parent 對象對應(yīng)起來,因此它不格外包含其他值。
所有這些對象都是 window 對象的屬性,可以通過 window.parent、window.top 等形式來訪問。同時(shí),這也意味著可以將不同層次的 window 對象連綴起來,例如 window.parent.parent.frames[0]。
在使用框架的情況下,瀏覽器中會(huì)存在多個(gè) Global 對象。在每個(gè)框架中定義的全局變量會(huì)自動(dòng)成為框架中 window 對象的屬性。由于每個(gè) window 對象都包含原生類型的構(gòu)造函數(shù),因此每個(gè)框架都有一套自己的構(gòu)造函數(shù),這些構(gòu)造函數(shù)一一對應(yīng),但并不相等。例如,top.Object 并不等于 top.frames[0].Object。這個(gè)問題會(huì)影響到對跨框架傳遞的對象使用 instanceof 運(yùn)算符。
導(dǎo)航和打開窗口使用 window.open() 方法既可以導(dǎo)航到一個(gè)特定的 URL,也可以打開一個(gè)新的瀏覽器窗口。這個(gè)方法可以接收4個(gè)參數(shù):要加載的URL、窗口目標(biāo)、一個(gè)特性字符串以及一個(gè)表示新頁面是否取代瀏覽器歷史記錄中當(dāng)前加載頁面的布爾值。通常只須傳遞第一個(gè)參數(shù),最后一個(gè)參數(shù)只在不打開新窗口的情況下使用。
如果為 window.open() 傳遞了第二個(gè)參數(shù),而且該參數(shù)是已有窗口或框架的名稱,那么就會(huì)在具有該名稱的窗口或框架中加載第一個(gè)參數(shù)指定的 URL。看下面的例子。
// 等同于 window.open("http://shijiajie.com/", "newWindow");彈出窗口
如果給 window.open() 傳遞的第二個(gè)參數(shù)并不是一個(gè)已經(jīng)存在的窗口或框架,那么該方法就會(huì)根據(jù)在第三個(gè)參數(shù)位置上傳入的字符串創(chuàng)建一個(gè)新窗口或新標(biāo)簽頁。如果沒有傳入第三個(gè)參數(shù),那么就會(huì)打開一個(gè)帶有全部默認(rèn)設(shè)置(工具欄、地址欄和狀態(tài)欄等)的新瀏覽器窗口(或者打開一個(gè)新標(biāo)簽頁)。在不打開新窗口的情況下,會(huì)忽略第三個(gè)參數(shù)。
第三個(gè)參數(shù)是一個(gè)逗號(hào)分隔的設(shè)置字符串,表示在新窗口中都顯示哪些特性。下表列出了可以出現(xiàn)在這個(gè)字符串中的設(shè)置選項(xiàng)。
設(shè)置 | 值 | 說明 |
---|---|---|
fullscreen | yes或no | 表示瀏覽器窗口是否最大化。僅限IE |
height | 數(shù)值 | 表示新窗口的高度。不能小于100 |
left | 數(shù)值 | 表示新窗口的左坐標(biāo)。不能是負(fù)值 |
location | yes或no | 表示是否在瀏覽器窗口中顯示地址欄。不同瀏覽器的默認(rèn)值不同。如果設(shè)置為no,地址欄可能會(huì)隱藏,也可能會(huì)被禁用(取決于瀏覽器) |
menubar | yes或no | 表示是否在瀏覽器窗口中顯示菜單欄。默認(rèn)值為no |
resizable | yes或no | 表示是否可以通過拖動(dòng)瀏覽器窗口的邊框改變其大小。默認(rèn)值為no |
scrollbars | yes或no | 表示如果內(nèi)容在視口中顯示不下,是否允許滾動(dòng)。默認(rèn)值為no |
status | yes或no | 表示是否在瀏覽器窗口中顯示狀態(tài)欄。默認(rèn)值為no |
toolbar | yes或no | 表示是否在瀏覽器窗口中顯示工具欄。默認(rèn)值為no |
top | 數(shù)值 | 表示新窗口的上坐標(biāo)。不能是負(fù)值 |
width | 數(shù)值 | 表示新窗口的寬度。不能小于100 |
這行代碼會(huì)打開一個(gè)新的可以調(diào)整大小的窗口,窗口初始大小為400×400像素,并且距屏幕上沿和左邊各10像素。
window.open("http://shijiajie.com/","newWindow", "height=400,width=400,top=10,left=10,resizable=yes");
window.open() 方法會(huì)返回一個(gè)指向新窗口的引用。引用的對象與其他 window 對象大致相似,但我們可以對其進(jìn)行更多控制。例如,有些瀏覽器在默認(rèn)情況下可能不允許我們針對主瀏覽器窗口調(diào)整大小或移動(dòng)位置,但卻允許我們針對通過window.open()創(chuàng)建的窗口調(diào)整大小或移動(dòng)位置。通過這個(gè)返回的對象,可以像操作其他窗口一樣操作新打開的窗口,如下所示。
var win = window.open("http://shijiajie.com/","newWindow", "height=400,width=400,top=10,left=10,resizable=yes"); // 調(diào)整大小 win.resizeTo(500,500); // 移動(dòng)位置 win.moveTo(100,100); // 關(guān)閉窗口 win.close();
但是,close() 方法僅適用于通過 window.open() 打開的彈出窗口。對于瀏覽器的主窗口,如果沒有得到用戶的允許是不能關(guān)閉它的。
新創(chuàng)建的 window 對象有一個(gè) opener 屬性,其中保存著打開它的原始窗口對象。這個(gè)屬性只在彈出窗口中的最外層 window 對象(top)中有定義,而且指向調(diào)用 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
雖然彈出窗口中有一個(gè)指針指向打開它的原始窗口,但原始窗口中并沒有這樣的指針指向彈出窗口。窗口并不跟蹤記錄它們打開的彈出窗口,因此我們只能在必要的時(shí)候自己來手動(dòng)實(shí)現(xiàn)跟蹤。
彈出窗口屏蔽程序曾經(jīng)有一段時(shí)間,廣告商在網(wǎng)上使用彈出窗口達(dá)到了肆無忌憚的程度。他們經(jīng)常把彈出窗口打扮成系統(tǒng)對話框的模樣,引誘用戶去點(diǎn)擊其中的廣告。由于看起來像是系統(tǒng)對話框,一般用戶很難分辨是真是假。為了解決這個(gè)問題,大多數(shù)瀏覽器內(nèi)置有彈出窗口屏蔽程序,將絕大多數(shù)用戶不想看到彈出窗口屏蔽掉。
于是,在彈出窗口被屏蔽時(shí),就應(yīng)該考慮兩種可能性。如果是瀏覽器內(nèi)置的屏蔽程序阻止的彈出窗口,那么 window.open() 很可能會(huì)返回 null,如果是瀏覽器擴(kuò)展或其他程序阻止的彈出窗口,那么 window.open() 通常會(huì)拋出一個(gè)錯(cuò)誤。因此,要想準(zhǔn)確地檢測出彈出窗口是否被屏蔽,必須在檢測返回值的同時(shí),將對 window.open() 的調(diào)用封裝在一個(gè) 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!"); }間歇調(diào)用和超時(shí)調(diào)用
JavaScript 是單線程語言,但它允許通過設(shè)置超時(shí)值和間歇時(shí)間值來調(diào)度代碼在特定的時(shí)刻執(zhí)行。前者是在指定的時(shí)間過后執(zhí)行代碼,而后者則是每隔指定的時(shí)間就執(zhí)行一次代碼。
超時(shí)調(diào)用需要使用 window 對象的 setTimeout() 方法,它接受兩個(gè)參數(shù):要執(zhí)行的代碼和以毫秒表示的時(shí)間(即在執(zhí)行代碼前需要等待多少毫秒)。其中,第一個(gè)參數(shù)可以是一個(gè)包含 JavaScript 代碼的字符串(就和在 eval() 函數(shù)中使用的字符串一樣),也可以是一個(gè)函數(shù)。例如,下面對 setTimeout() 的兩次調(diào)用都會(huì)在一秒鐘后顯示一個(gè)警告框。
// 不建議傳遞字符串 setTimeout("console.log("Hello world!") ", 1000); // 推薦的調(diào)用方式 setTimeout(function() { console.log("Hello world!"); }, 1000);
雖然這兩種調(diào)用方式都沒有問題,但由于傳遞字符串可能導(dǎo)致性能損失,因此不建議以字符串作為第一個(gè)參數(shù)。
第二個(gè)參數(shù)是一個(gè)表示等待多長時(shí)間的毫秒數(shù),但經(jīng)過該時(shí)間后指定的代碼不一定會(huì)執(zhí)行。JavaScript 是一個(gè)單線程序的解釋器,因此一定時(shí)間內(nèi)只能執(zhí)行一段代碼。為了控制要執(zhí)行的代碼,就有一個(gè) JavaScript 任務(wù)隊(duì)列。這些任務(wù)會(huì)按照將它們添加到隊(duì)列的順序執(zhí)行。setTimeout() 的第二個(gè)參數(shù)告訴 JavaScript 再過多長時(shí)間把當(dāng)前任務(wù)添加到隊(duì)列中。如果隊(duì)列是空的,那么添加的代碼會(huì)立即執(zhí)行;如果隊(duì)列不是空的,那么它就要等前面的代碼執(zhí)行完了以后再執(zhí)行。
調(diào)用 setTimeout() 之后,該方法會(huì)返回一個(gè)數(shù)值 ID,表示超時(shí)調(diào)用。這個(gè)超時(shí)調(diào)用 ID 是計(jì)劃執(zhí)行代碼的唯一標(biāo)識(shí)符,可以通過它來取消超時(shí)調(diào)用。要取消尚未執(zhí)行的超時(shí)調(diào)用計(jì)劃,可以調(diào)用 clearTimeout() 方法并將相應(yīng)的超時(shí)調(diào)用 ID 作為參數(shù)傳遞給它,如下所示。
// 設(shè)置超時(shí)調(diào)用 var timeoutId = setTimeout(function() { console.log("Hello world!"); }, 1000); // 注意:把它取消 clearTimeout(timeoutId);
只要是在指定的時(shí)間尚未過去之前調(diào)用 clearTimeout(),就可以完全取消超時(shí)調(diào)用。前面的代碼在設(shè)置超時(shí)調(diào)用之后馬上又調(diào)用了 clearTimeout(),結(jié)果就跟什么也沒有發(fā)生一樣。
間歇調(diào)用與超時(shí)調(diào)用類似,只不過它會(huì)按照指定的時(shí)間間隔重復(fù)執(zhí)行代碼,直至間歇調(diào)用被取消或者頁面被卸載。設(shè)置間歇調(diào)用的方法是 setInterval(),它接受的參數(shù)與 setTimeout() 相同:要執(zhí)行的代碼(字符串或函數(shù))和每次執(zhí)行之前需要等待的毫秒數(shù)。下面來看一個(gè)例子。
// 不建議傳遞字符串 setInterval ("console.log("Hello world!") ", 10000); // 推薦的調(diào)用方式 setInterval (function() { console.log("Hello world!"); }, 10000);
調(diào)用 setInterval() 方法同樣也會(huì)返回一個(gè)間歇調(diào)用 ID,該 ID 可用于在將來某個(gè)時(shí)刻取消間歇調(diào)用。要取消尚未執(zhí)行的間歇調(diào)用,可以使用 clearInterval() 方法并傳入相應(yīng)的間歇調(diào)用 ID。取消間歇調(diào)用的重要性要遠(yuǎn)遠(yuǎn)高于取消超時(shí)調(diào)用,因?yàn)樵诓患痈缮娴那闆r下,間歇調(diào)用將會(huì)一直執(zhí)行到頁面卸載。以下是一個(gè)常見的使用間歇調(diào)用的例子。
var num = 0; var max = 10; var intervalId = null; function incrementNumber() { num++; // 如果執(zhí)行次數(shù)達(dá)到了max設(shè)定的值,則取消后續(xù)尚未執(zhí)行的調(diào)用 if (num == max) { clearInterval(intervalId); console.log("Done"); } } intervalId = setInterval(incrementNumber, 500);
在這個(gè)例子中,變量num每半秒鐘遞增一次,當(dāng)遞增到最大值時(shí)就會(huì)取消先前設(shè)定的間歇調(diào)用。這個(gè)模式也可以使用超時(shí)調(diào)用來實(shí)現(xiàn),如下所示。
var num = 0; var max = 10; function incrementNumber() { num++; // 如果執(zhí)行次數(shù)未達(dá)到max設(shè)定的值,則設(shè)置另一次超時(shí)調(diào)用 if (num < max) { setTimeout(incrementNumber, 500); } else { console.log("Done"); } } setTimeout(incrementNumber, 500);
可見,在使用超時(shí)調(diào)用時(shí),沒有必要跟蹤超時(shí)調(diào)用 ID,因?yàn)槊看螆?zhí)行代碼之后,如果不再設(shè)置另一次超時(shí)調(diào)用,調(diào)用就會(huì)自行停止。一般認(rèn)為,使用超時(shí)調(diào)用來模擬間歇調(diào)用的是一種最佳模式。在開發(fā)環(huán)境下,很少使用真正的間歇調(diào)用,原因是后一個(gè)間歇調(diào)用可能會(huì)在前一個(gè)間歇調(diào)用結(jié)束之前啟動(dòng)。而像前面示例中那樣使用超時(shí)調(diào)用,則完全可以避免這一點(diǎn)。所以,最好不要使用間歇調(diào)用。
系統(tǒng)對話框瀏覽器通過 alert()、confirm() 和 prompt() 方法可以調(diào)用系統(tǒng)對話框向用戶顯示消息。系統(tǒng)對話框與在瀏覽器中顯示的網(wǎng)頁沒有關(guān)系,也不包含 HTML。它們的外觀由操作系統(tǒng)及(或)瀏覽器設(shè)置決定,而不是由 CSS 決定。此外,通過這幾個(gè)方法打開的對話框都是同步和模態(tài)的。也就是說,顯示這些對話框的時(shí)候代碼會(huì)停止執(zhí)行,而關(guān)掉這些對話框后代碼又會(huì)恢復(fù)執(zhí)行。
第一種對話框是調(diào)用 alert() 方法生成的。它向用戶顯示一個(gè)系統(tǒng)對話框,其中包含指定的文本和一個(gè) OK(“確定”)按鈕。通常使用 alert() 生成的“警告”對話框向用戶顯示一些他們無法控制的消息,例如錯(cuò)誤消息。而用戶只能在看完消息后關(guān)閉對話框。
第二種對話框是調(diào)用 confirm() 方法生成的。從向用戶顯示消息的方面來看,這種“確認(rèn)”對話框很像是一個(gè)“警告”對話框。但二者的主要區(qū)別在于“確認(rèn)”對話框除了顯示OK按鈕外,還會(huì)顯示一個(gè) Cancel(“取消”)按鈕,兩個(gè)按鈕可以讓用戶決定是否執(zhí)行給定的操作。
為了確定用戶是單擊了OK還是Cancel,可以檢查 confirm() 方法返回的布爾值:true 表示單擊了OK,false 表示單擊了Cancel或單擊了右上角的 X 按鈕。確認(rèn)對話框的典型用法如下。
if (confirm("Are you sure?")) { alert("I"m so glad you"re sure! "); } else { alert("I"m sorry to hear you"re not sure."); }
最后一種對話框是通過調(diào)用 prompt() 方法生成的,這是一個(gè)“提示”框,用于提示用戶輸入一些文本。提示框中除了顯示 OK 和 Cancel 按鈕之外,還會(huì)顯示一個(gè)文本輸入域,以供用戶在其中輸入內(nèi)容。prompt() 方法接受兩個(gè)參數(shù):要顯示給用戶的文本提示和文本輸入域的默認(rèn)值(可以是一個(gè)空字符串)。
如果用戶單擊了 OK 按鈕,則 promp() 返回文本輸入域的值;如果用戶單擊了 Cancel 或沒有單擊 OK 而是通過其他方式關(guān)閉了對話框,則該方法返回 null。下面是一個(gè)例子。
var result = prompt("What is your name? ", ""); if (result !== null) { alert("Welcome, " + result); }
綜上所述,這些系統(tǒng)對話框很適合向用戶顯示消息并請用戶作出決定。由于不涉及 HTML、CSS 或 JavaScript,因此它們是增強(qiáng) Web 應(yīng)用程序的一種便捷方式。
location 對象location 對象提供了與當(dāng)前窗口中加載的文檔有關(guān)的信息,還提供了一些導(dǎo)航功能。事實(shí)上,location 對象是很特別的一個(gè)對象,因?yàn)樗仁?window 對象的屬性,也是 document 對象的屬性;換句話說,window.location 和 document.location 引用的是同一個(gè)對象。location 對象的用處不只表現(xiàn)在它保存著當(dāng)前文檔的信息,還表現(xiàn)在它將 URL 解析為獨(dú)立的片段,讓開發(fā)人員可以通過不同的屬性訪問這些片段。下表列出了 location 對象的所有屬性。
屬性名 | 例子 | 說明 |
---|---|---|
hash | "#contents" | 返回 URL 中的 hash(#號(hào)后跟零或多個(gè)字符),如果 URL 中不包含散列,則返回空字符串 |
host | "shijiajie.com:80" | 返回服務(wù)器名稱和端口號(hào)(如果有) |
hostname | "shijiajie.com" | 返回不帶端口號(hào)的服務(wù)器名稱 |
href | "http:/shijiajie.com" | 返回當(dāng)前加載頁面的完整URL。而 location 對象的 toString() 方法也返回這個(gè)值 |
pathname | "/WileyCDA/" | 返回URL中的目錄和(或)文件名 |
port | "8080" | 返回 URL 中指定的端口號(hào)。如果 URL 中不包含端口號(hào),則這個(gè)屬性返回空字符串 |
protocol | "http:" | 返回頁面使用的協(xié)議。通常是 http: 或 https: |
search | "?q=javascript" | 返回URL的查詢字符串。這個(gè)字符串以問號(hào)開頭 |
雖然通過上面的屬性可以訪問到 location 對象的大多數(shù)信息,但其中訪問URL包含的查詢字符串的屬性并不方便。盡管 location.search 返回從問號(hào)到 URL 末尾的所有內(nèi)容,但卻沒有辦法逐個(gè)訪問其中的每個(gè)查詢字符串參數(shù)。為此,可以像下面這樣創(chuàng)建一個(gè)函數(shù),用以解析查詢字符串,然后返回包含所有參數(shù)的一個(gè)對象:
/* * 這個(gè)函數(shù)用來解析來自URL的查詢串中的name=value參數(shù)對 * 它將name=value對存儲(chǔ)在一個(gè)對象的屬性中,并返回該對象 * 這樣來使用它 * * var args = urlArgs(); // 從URL中解析參數(shù) * var q = args.q || ""; // 如果參數(shù)定義了的話就使用參數(shù);否則使用一個(gè)默認(rèn)值 * var n = args.n ? parseInt(args.n) : 10; */ function urlArgs() { var args = {}; // 定義一個(gè)空對象 var query = location.search.substring(1); // 查找到查詢串,并去掉"? " var pairs = query.split("&"); // 根據(jù)"&"符號(hào)將查詢字符串分隔開 for (var i = 0; i < pairs.length; i++) { // 對于每個(gè)片段 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進(jìn)行解碼 args[name] = value; // 存儲(chǔ)為屬性 } return args; // 返回解析后的參數(shù) }位置操作
使用 location 對象可以通過很多方式來改變?yōu)g覽器的位置。首先,也是最常用的方式,就是使用 assign()方法并為其傳遞一個(gè) URL,如下所示。
location.assign("http://shijiajie.com");
這樣,就可以立即打開新URL并在瀏覽器的歷史記錄中生成一條記錄。如果是將 location.href 或 window.location 設(shè)置為一個(gè)URL值,也會(huì)以該值調(diào)用 assign() 方法。例如,下列兩行代碼與顯式調(diào)用 assign() 方法的效果完全一樣。
window.location = "http://shijiajie.com"; location.href = "http://shijiajie.com";
在這些改變?yōu)g覽器位置的方法中,最常用的是設(shè)置 location.href 屬性。
另外,修改 location 對象的其他屬性也可以改變當(dāng)前加載的頁面。下面的例子展示了通過將 hash、search、hostname、pathname 和 port 屬性設(shè)置為新值來改變 URL。
// 假設(shè)初始 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;
當(dāng)通過上述任何一種方式修改URL之后,瀏覽器的歷史記錄中就會(huì)生成一條新記錄,因此用戶通過單擊“后退”按鈕都會(huì)導(dǎo)航到前一個(gè)頁面。要禁用這種行為,可以使用 replace() 方法。這個(gè)方法只接受一個(gè)參數(shù),即要導(dǎo)航到的 URL;結(jié)果雖然會(huì)導(dǎo)致瀏覽器位置改變,但不會(huì)在歷史記錄中生成新記錄。在調(diào)用 replace() 方法之后,用戶不能回到前一個(gè)頁面,來看下面的例子:
You won"t be able to get back here Enjoy this page for a second, because you won"t be coming back here.
如果將這個(gè)頁面加載到瀏覽器中,瀏覽器就會(huì)在1秒鐘后重新定向到 shijiajie.com。然后,“后退”按鈕將處于禁用狀態(tài),如果不重新輸入完整的 URL,則無法返回示例頁面。
與位置有關(guān)的最后一個(gè)方法是 reload(),作用是重新加載當(dāng)前顯示的頁面。如果調(diào)用 reload() 時(shí)不傳遞任何參數(shù),頁面就會(huì)以最有效的方式重新加載。也就是說,如果頁面自上次請求以來并沒有改變過,頁面就會(huì)從瀏覽器緩存中重新加載。如果要強(qiáng)制從服務(wù)器重新加載,則需要像下面這樣為該方法傳遞參數(shù) true。
location.reload(); // 重新加載(有可能從緩存中加載) location.reload(true); // 重新加載(從服務(wù)器重新加載)
位于 reload() 調(diào)用之后的代碼可能會(huì)也可能不會(huì)執(zhí)行,這要取決于網(wǎng)絡(luò)延遲或系統(tǒng)資源等因素。為此,最好將 reload() 放在代碼的最后一行。
history 對象history 對象保存著用戶上網(wǎng)的歷史記錄,從窗口被打開的那一刻算起。因?yàn)?history 是 window 對象的屬性,因此每個(gè)瀏覽器窗口、每個(gè)標(biāo)簽頁乃至每個(gè)框架,都有自己的 history 對象與特定的 window 對象關(guān)聯(lián)。出于安全方面的考慮,開發(fā)人員無法得知用戶瀏覽過的 URL。不過,借由用戶訪問過的頁面列表,同樣可以在不知道實(shí)際 URL 的情況下實(shí)現(xiàn)后退和前進(jìn)。
使用 go() 方法可以在用戶的歷史記錄中任意跳轉(zhuǎn),可以向后也可以向前。這個(gè)方法接受一個(gè)參數(shù),表示向后或向前跳轉(zhuǎn)的頁面數(shù)的一個(gè)整數(shù)值。負(fù)數(shù)表示向后跳轉(zhuǎn)(類似于單擊瀏覽器的“后退”按鈕),正數(shù)表示向前跳轉(zhuǎn)(類似于單擊瀏覽器的“前進(jìn)”按鈕)。來看下面的例子。
// 后退一頁 history.go(-1); // 前進(jìn)一頁 history.go(1); // 前進(jìn)兩頁 history.go(2);
也可以給 go() 方法傳遞一個(gè)字符串參數(shù),此時(shí)瀏覽器會(huì)跳轉(zhuǎn)到歷史記錄中包含該字符串的第一個(gè)位置——可能后退,也可能前進(jìn),具體要看哪個(gè)位置最近。如果歷史記錄中不包含該字符串,那么這個(gè)方法什么也不做,例如:
// 跳轉(zhuǎn)到最近的 shijiajie.com 頁面 history.go("shijiajie.com");
另外,還可以使用兩個(gè)簡寫方法 back() 和 forward() 來代替 go()。顧名思義,這兩個(gè)方法可以模仿瀏覽器的“后退”和“前進(jìn)”按鈕。
// 后退一頁 history.back(); // 前進(jìn)一頁 history.forward();
除了上述幾個(gè)方法外,history 對象還有一個(gè) length 屬性,保存著歷史記錄的數(shù)量。這個(gè)數(shù)量包括所有歷史記錄,即所有向后和向前的記錄。對于加載到窗口、標(biāo)簽頁或框架中的第一個(gè)頁面而言,history.length 等于0。通過像下面這樣測試該屬性的值,可以確定用戶是否一開始就打開了你的頁面。
if (history.length == 0){ //這應(yīng)該是用戶打開窗口后的第一個(gè)頁面 }
雖然 history 并不常用,但在創(chuàng)建自定義的“后退”和“前進(jìn)”按鈕,以及檢測當(dāng)前頁面是不是用戶歷史記錄中的第一個(gè)頁面時(shí),還是必須使用它。
小結(jié)BOM(瀏覽器對象模型)以 window 對象為依托,表示瀏覽器窗口以及頁面可見區(qū)域。同時(shí),window 對象還是 ECMAScript 中的 Global 對象,因而所有全局變量和函數(shù)都是它的屬性,且所有原生的構(gòu)造函數(shù)及其他函數(shù)也都存在于它的命名空間下。本章討論了下列 BOM 的組成部分。
在使用框架時(shí),每個(gè)框架都有自己的 window 對象以及所有原生構(gòu)造函數(shù)及其他函數(shù)的副本。每個(gè)框架都保存在 frames 集合中,可以通過位置或通過名稱來訪問。
有一些窗口指針,可以用來引用其他框架,包括父框架。
top 對象始終指向最外圍的框架,也就是整個(gè)瀏覽器窗口。
parent 對象表示包含當(dāng)前框架的框架,而 self 對象則回指 window。
使用 location 對象可以通過編程方式來訪問瀏覽器的導(dǎo)航系統(tǒng)。設(shè)置相應(yīng)的屬性,可以逐段或整體性地修改瀏覽器的 URL。
調(diào)用 replace() 方法可以導(dǎo)航到一個(gè)新 URL,同時(shí)該 URL 會(huì)替換瀏覽器歷史記錄中當(dāng)前顯示的頁面。
navigator 對象提供了與瀏覽器有關(guān)的信息。到底提供哪些信息,很大程度上取決于用戶的瀏覽器;不過,也有一些公共的屬性(如 userAgent)存在于所有瀏覽器中。
BOM中還有兩個(gè)對象:screen 和 history,但它們的功能有限。screen 對象中保存著與客戶端顯示器有關(guān)的信息,這些信息一般只用于站點(diǎn)分析。history 對象為訪問瀏覽器的歷史記錄開了一個(gè)小縫隙,開發(fā)人員可以據(jù)此判斷歷史記錄的數(shù)量,也可以在歷史記錄中向后或向前導(dǎo)航到任意頁面。
關(guān)卡// 挑戰(zhàn)一 setTimeout(function () { console.log("1"); }, 0) console.log("2"); // ???
// 挑戰(zhàn)二 for (var i = 0;i<5;i++) { setTimeout(function () { console.log(i); // ??? }, 0) };
// 挑戰(zhàn)三 var a = 1; var obj = { a : 2, b : function(){ setTimeout(function () { console.log(this.a); }, 0) } } obj.b(); // ???
// 挑戰(zhàn)四 var a = 1; var obj = { a : 2, b : function(){ setTimeout(function () { console.log(this.a); }.call(this), 0); } } obj.b(); // ???更多
關(guān)注微信公眾號(hào)「劼哥舍」回復(fù)「答案」,獲取關(guān)卡詳解。
關(guān)注 https://github.com/stone0090/javascript-lessons,獲取最新動(dòng)態(tài)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/80797.html
摘要:對象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對象模型是針對和文檔的一個(gè)。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動(dòng)態(tài)的,根闖關(guān)記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...
摘要:瀏覽器只是實(shí)現(xiàn)的宿主環(huán)境之一,其他宿主環(huán)境包括和。年月,版發(fā)布,成為國際標(biāo)準(zhǔn)。事件定義了事件和事件處理的接口。對于已經(jīng)正式納入標(biāo)準(zhǔn)的來說,盡管各瀏覽器都實(shí)現(xiàn)了某些眾所周知的共同特性,但其他特性還是會(huì)因?yàn)g覽器而異。 JavaScript 是面向 Web 的編程語言,絕大多數(shù)現(xiàn)代網(wǎng)站都使用了 JavaScript,并且所有的現(xiàn)代 Web 瀏覽器(電腦,手機(jī),平板)均包含了 JavaScri...
摘要:本課程之所以叫做闖關(guān)記,是因?yàn)椴糠终鹿?jié)精心設(shè)計(jì)了挑戰(zhàn)關(guān)卡,通過提供更多的實(shí)戰(zhàn)機(jī)會(huì),讓大家可以循序漸進(jìn)地有目的地有挑戰(zhàn)地開展學(xué)習(xí)。課程結(jié)構(gòu)及目錄以下目錄只是初步構(gòu)想,課程結(jié)構(gòu)及內(nèi)容會(huì)根據(jù)實(shí)際情況隨時(shí)進(jìn)行調(diào)整。 為何寫作此課程 stone 主要負(fù)責(zé)基于 Web 的企業(yè)內(nèi)部管理系統(tǒng)的開發(fā),雖然能夠熟練地使用 JavaScript,但隨著對 JavaScript 的理解越來越深,才發(fā)現(xiàn)自己尚...
摘要:內(nèi)存回收此時(shí),局部變量就沒有存在的必要了,因此可以釋放它們的內(nèi)存以供將來使用。局部變量會(huì)在它們離開執(zhí)行環(huán)境時(shí)自動(dòng)被解除引用,如下面這個(gè)例子所示手工解除的引用由于局部變量在函數(shù)執(zhí)行完畢后就離開了其執(zhí)行環(huán)境,因此無需我們顯式地去為它解除引用。 JavaScript 具有自動(dòng)垃圾收集機(jī)制(GC:Garbage Collecation),也就是說,執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過程中使用的內(nèi)存。而...
摘要:使用元素嵌入代碼時(shí),只需為指定屬性。需要注意的是,帶有屬性的元素不應(yīng)該在其和元素之間再包含額外的代碼。在包含外部文件時(shí),必須將屬性設(shè)置為指向相應(yīng)文件的。所有元素都會(huì)按照他們在頁面中出現(xiàn)的先后順序依次被解析。關(guān)注,獲取最新動(dòng)態(tài)。 當(dāng)學(xué)習(xí)一門新的編程語言的時(shí)候,應(yīng)該邊學(xué)邊做,反復(fù)演練以加深理解。因此,你需要一個(gè) JavaScript 解釋器。幸運(yùn)的是,每一個(gè) Web 瀏覽器都包含一個(gè) Ja...
閱讀 2835·2021-11-19 09:40
閱讀 5692·2021-09-27 14:10
閱讀 2168·2021-09-04 16:45
閱讀 1569·2021-07-25 21:37
閱讀 3057·2019-08-30 10:57
閱讀 3058·2019-08-28 17:59
閱讀 1115·2019-08-26 13:46
閱讀 1475·2019-08-26 13:27