亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

《JavaScript 闖關(guān)記》之 BOM

馬忠志 / 2113人閱讀

摘要:對象的核心對象是,它表示瀏覽器的一個(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í)際上,selfwindow 對象可以互換使用。引入 self 對象的目的只是為了與 topparent 對象對應(yīng)起來,因此它不格外包含其他值。

所有這些對象都是 window 對象的屬性,可以通過 window.parentwindow.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.locationdocument.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)開頭
查詢字符串參數(shù)

雖然通過上面的屬性可以訪問到 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.hrefwindow.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、pathnameport 屬性設(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)?historywindow 對象的屬性,因此每個(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è)對象:screenhistory,但它們的功能有限。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

相關(guān)文章

  • JavaScript 闖關(guān)

    摘要:對象數(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 元素...

    mj 評論0 收藏0
  • JavaScript 闖關(guān)簡介

    摘要:瀏覽器只是實(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...

    baihe 評論0 收藏0
  • JavaScript 闖關(guān)

    摘要:本課程之所以叫做闖關(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)自己尚...

    curried 評論0 收藏0
  • JavaScript 闖關(guān)垃圾回收和內(nèi)存管理

    摘要:內(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)存。而...

    Sleepy 評論0 收藏0
  • JavaScript 闖關(guān)初探

    摘要:使用元素嵌入代碼時(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...

    atinosun 評論0 收藏0

發(fā)表評論

0條評論

最新活動(dòng)
閱讀需要支付1元查看
<