成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

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

馬忠志 / 2061人閱讀

摘要:對(duì)象的核心對(duì)象是,它表示瀏覽器的一個(gè)實(shí)例。及更高版本不會(huì)拋出錯(cuò)誤。與框架有關(guān)的最后一個(gè)對(duì)象是,它始終指向?qū)嶋H上,和對(duì)象可以互換使用。設(shè)置值說(shuō)明或表示瀏覽器窗口是否最大化。僅限數(shù)值表示新窗口的高度。

ECMAScript 是 JavaScript 的核心,但如果要在 Web 中使用 JavaScript,那么 BOM(瀏覽器對(duì)象模型)則無(wú)疑才是真正的核心。BOM 提供了很多對(duì)象,用于訪問(wèn)瀏覽器的功能,這些功能與任何網(wǎng)頁(yè)內(nèi)容無(wú)關(guān)。多年來(lái),缺少事實(shí)上的規(guī)范導(dǎo)致 BOM 有很多問(wèn)題,因?yàn)闉g覽器提供商會(huì)按照各自的想法隨意去擴(kuò)展它。W3C 為了把瀏覽器中 JavaScript 最基本的部分標(biāo)準(zhǔn)化,已經(jīng)將 BOM 的主要方面納入了 HTML5 的規(guī)范中。

window 對(duì)象

BOM 的核心對(duì)象是 window,它表示瀏覽器的一個(gè)實(shí)例。在瀏覽器中,window 對(duì)象有雙重角色,它既是通過(guò) JavaScript 訪問(wèn)瀏覽器窗口的一個(gè)接口,又是 ECMAScript 規(guī)定的 Global 對(duì)象。這意味著在網(wǎng)頁(yè)中定義的任何一個(gè)對(duì)象、變量和函數(shù),都以 window 作為其 Global 對(duì)象,因此有權(quán)訪問(wèn) isNaN()、isFinite()parseInt()、parseFloat() 等方法。

全局作用域

由于 window 對(duì)象同時(shí)扮演著 ECMAScript 中 Global 對(duì)象的角色,因此所有在全局作用域中聲明的變量、函數(shù)都會(huì)變成 window 對(duì)象的屬性和方法。來(lái)看下面的例子。

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

console.log(window.age);    // 29
sayAge();                   // 29
window.sayAge();            // 29

拋開(kāi)全局變量會(huì)成為 window 對(duì)象的屬性不談,定義全局變量與在 window 對(duì)象上直接定義屬性還是有一點(diǎn)差別:全局變量不能通過(guò) delete 運(yùn)算符刪除,而直接在 window 對(duì)象上的定義的屬性可以。例如:

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 語(yǔ)句添加的 window 屬性有一個(gè)名為 Configurable 的特性,這個(gè)特性的值被默認(rèn)設(shè)置為 false,因此這樣定義的屬性不可以通過(guò) delete 運(yùn)算符刪除。IE8 及更早版本在遇到使用 delete 刪除 window 屬性的語(yǔ)句時(shí),不管該屬性最初是如何創(chuàng)建的,都會(huì)拋出錯(cuò)誤,以示警告。IE9 及更高版本不會(huì)拋出錯(cuò)誤。

另外,還要記住一件事:嘗試訪問(wèn)未聲明的變量會(huì)拋出錯(cuò)誤,但是通過(guò)查詢 window 對(duì)象,可以知道某個(gè)可能未聲明的變量是否存在。例如:

// 這里會(huì)拋出錯(cuò)誤,因?yàn)?oldValue 未定義
var newValue = oldValue;

// 這里不會(huì)拋出錯(cuò)誤,因?yàn)檫@是一次屬性查詢
// newValue 的值是 undefined
var newValue = window.oldValue;
窗口關(guān)系及框架

如果頁(yè)面中包含框架,則每個(gè)框架都擁有自己的 window 對(duì)象,并且保存在 frames 集合中。在 frames 集合中,可以通過(guò)數(shù)值索引(從0開(kāi)始,從左至右,從上到下)或者框架名稱來(lái)訪問(wèn)相應(yīng)的 window 對(duì)象。每個(gè) window 對(duì)象都有一個(gè) name 屬性,其中包含框架的名稱。下面是一個(gè)包含框架的頁(yè)面:


    
        Frameset Example
    
    
        
        
            
            
        
    

對(duì)這個(gè)例子而言,可以通過(guò) window.frames[0] 或者 window.frames["topFrame"] 來(lái)引用上方的框架。不過(guò)最好使用 top 而非 window 來(lái)引用這些框架(例如 top.frames[0]),因?yàn)?top 對(duì)象始終指向最高(最外)層的框架,也就是瀏覽器窗口。使用它可以確保在一個(gè)框架中正確地訪問(wèn)另一個(gè)框架。因?yàn)閷?duì)于在一個(gè)框架中編寫(xiě)的任何代碼來(lái)說(shuō),其中的 window 對(duì)象指向的都是那個(gè)框架的特定實(shí)例,而非最高層的框架。

top 相對(duì)的另一個(gè) window 對(duì)象是 parent。顧名思義,parent(父)對(duì)象始終指向當(dāng)前框架的直接上層框架。在某些情況下,parent 有可能等于 top;但在沒(méi)有框架的情況下,parent 一定等于 top(此時(shí)它們都等于 window)。

與框架有關(guān)的最后一個(gè)對(duì)象是 self,它始終指向 window;實(shí)際上,selfwindow 對(duì)象可以互換使用。引入 self 對(duì)象的目的只是為了與 topparent 對(duì)象對(duì)應(yīng)起來(lái),因此它不格外包含其他值。

所有這些對(duì)象都是 window 對(duì)象的屬性,可以通過(guò) window.parentwindow.top 等形式來(lái)訪問(wèn)。同時(shí),這也意味著可以將不同層次的 window 對(duì)象連綴起來(lái),例如 window.parent.parent.frames[0]。

在使用框架的情況下,瀏覽器中會(huì)存在多個(gè) Global 對(duì)象。在每個(gè)框架中定義的全局變量會(huì)自動(dòng)成為框架中 window 對(duì)象的屬性。由于每個(gè) window 對(duì)象都包含原生類型的構(gòu)造函數(shù),因此每個(gè)框架都有一套自己的構(gòu)造函數(shù),這些構(gòu)造函數(shù)一一對(duì)應(yīng),但并不相等。例如,top.Object 并不等于 top.frames[0].Object。這個(gè)問(wèn)題會(huì)影響到對(duì)跨框架傳遞的對(duì)象使用 instanceof 運(yùn)算符。

導(dǎo)航和打開(kāi)窗口

使用 window.open() 方法既可以導(dǎo)航到一個(gè)特定的 URL,也可以打開(kāi)一個(gè)新的瀏覽器窗口。這個(gè)方法可以接收4個(gè)參數(shù):要加載的URL、窗口目標(biāo)、一個(gè)特性字符串以及一個(gè)表示新頁(yè)面是否取代瀏覽器歷史記錄中當(dāng)前加載頁(yè)面的布爾值。通常只須傳遞第一個(gè)參數(shù),最后一個(gè)參數(shù)只在不打開(kāi)新窗口的情況下使用。

如果為 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)簽頁(yè)。如果沒(méi)有傳入第三個(gè)參數(shù),那么就會(huì)打開(kāi)一個(gè)帶有全部默認(rèn)設(shè)置(工具欄、地址欄和狀態(tài)欄等)的新瀏覽器窗口(或者打開(kāi)一個(gè)新標(biāo)簽頁(yè))。在不打開(kāi)新窗口的情況下,會(huì)忽略第三個(gè)參數(shù)。

第三個(gè)參數(shù)是一個(gè)逗號(hào)分隔的設(shè)置字符串,表示在新窗口中都顯示哪些特性。下表列出了可以出現(xiàn)在這個(gè)字符串中的設(shè)置選項(xiàng)。

設(shè)置 說(shuō)明
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 表示是否可以通過(guò)拖動(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ì)打開(kāi)一個(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è)指向新窗口的引用。引用的對(duì)象與其他 window 對(duì)象大致相似,但我們可以對(duì)其進(jìn)行更多控制。例如,有些瀏覽器在默認(rèn)情況下可能不允許我們針對(duì)主瀏覽器窗口調(diào)整大小或移動(dòng)位置,但卻允許我們針對(duì)通過(guò)window.open()創(chuàng)建的窗口調(diào)整大小或移動(dòng)位置。通過(guò)這個(gè)返回的對(duì)象,可以像操作其他窗口一樣操作新打開(kāi)的窗口,如下所示。

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() 方法僅適用于通過(guò) window.open() 打開(kāi)的彈出窗口。對(duì)于瀏覽器的主窗口,如果沒(méi)有得到用戶的允許是不能關(guān)閉它的。

新創(chuàng)建的 window 對(duì)象有一個(gè) opener 屬性,其中保存著打開(kāi)它的原始窗口對(duì)象。這個(gè)屬性只在彈出窗口中的最外層 window 對(duì)象(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è)指針指向打開(kāi)它的原始窗口,但原始窗口中并沒(méi)有這樣的指針指向彈出窗口。窗口并不跟蹤記錄它們打開(kāi)的彈出窗口,因此我們只能在必要的時(shí)候自己來(lái)手動(dòng)實(shí)現(xiàn)跟蹤。

彈出窗口屏蔽程序

曾經(jīng)有一段時(shí)間,廣告商在網(wǎng)上使用彈出窗口達(dá)到了肆無(wú)忌憚的程度。他們經(jīng)常把彈出窗口打扮成系統(tǒng)對(duì)話框的模樣,引誘用戶去點(diǎn)擊其中的廣告。由于看起來(lái)像是系統(tǒng)對(duì)話框,一般用戶很難分辨是真是假。為了解決這個(gè)問(wèn)題,大多數(shù)瀏覽器內(nèi)置有彈出窗口屏蔽程序,將絕大多數(shù)用戶不想看到彈出窗口屏蔽掉。

于是,在彈出窗口被屏蔽時(shí),就應(yīng)該考慮兩種可能性。如果是瀏覽器內(nèi)置的屏蔽程序阻止的彈出窗口,那么 window.open() 很可能會(huì)返回 null,如果是瀏覽器擴(kuò)展或其他程序阻止的彈出窗口,那么 window.open() 通常會(huì)拋出一個(gè)錯(cuò)誤。因此,要想準(zhǔn)確地檢測(cè)出彈出窗口是否被屏蔽,必須在檢測(cè)返回值的同時(shí),將對(duì) 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 是單線程語(yǔ)言,但它允許通過(guò)設(shè)置超時(shí)值和間歇時(shí)間值來(lái)調(diào)度代碼在特定的時(shí)刻執(zhí)行。前者是在指定的時(shí)間過(guò)后執(zhí)行代碼,而后者則是每隔指定的時(shí)間就執(zhí)行一次代碼。

超時(shí)調(diào)用需要使用 window 對(duì)象的 setTimeout() 方法,它接受兩個(gè)參數(shù):要執(zhí)行的代碼和以毫秒表示的時(shí)間(即在執(zhí)行代碼前需要等待多少毫秒)。其中,第一個(gè)參數(shù)可以是一個(gè)包含 JavaScript 代碼的字符串(就和在 eval() 函數(shù)中使用的字符串一樣),也可以是一個(gè)函數(shù)。例如,下面對(duì) setTimeout() 的兩次調(diào)用都會(huì)在一秒鐘后顯示一個(gè)警告框。

// 不建議傳遞字符串
setTimeout("console.log("Hello world!") ", 1000);

// 推薦的調(diào)用方式
setTimeout(function() { 
    console.log("Hello world!"); 
}, 1000);

雖然這兩種調(diào)用方式都沒(méi)有問(wèn)題,但由于傳遞字符串可能導(dǎo)致性能損失,因此不建議以字符串作為第一個(gè)參數(shù)。

第二個(gè)參數(shù)是一個(gè)表示等待多長(zhǎng)時(shí)間的毫秒數(shù),但經(jīng)過(guò)該時(shí)間后指定的代碼不一定會(huì)執(zhí)行。JavaScript 是一個(gè)單線程序的解釋器,因此一定時(shí)間內(nèi)只能執(zhí)行一段代碼。為了控制要執(zhí)行的代碼,就有一個(gè) JavaScript 任務(wù)隊(duì)列。這些任務(wù)會(huì)按照將它們添加到隊(duì)列的順序執(zhí)行。setTimeout() 的第二個(gè)參數(shù)告訴 JavaScript 再過(guò)多長(zhǎng)時(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í)符,可以通過(guò)它來(lái)取消超時(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í)間尚未過(guò)去之前調(diào)用 clearTimeout(),就可以完全取消超時(shí)調(diào)用。前面的代碼在設(shè)置超時(shí)調(diào)用之后馬上又調(diào)用了 clearTimeout(),結(jié)果就跟什么也沒(méi)有發(fā)生一樣。

間歇調(diào)用與超時(shí)調(diào)用類似,只不過(guò)它會(huì)按照指定的時(shí)間間隔重復(fù)執(zhí)行代碼,直至間歇調(diào)用被取消或者頁(yè)面被卸載。設(shè)置間歇調(diào)用的方法是 setInterval(),它接受的參數(shù)與 setTimeout() 相同:要執(zhí)行的代碼(字符串或函數(shù))和每次執(zhí)行之前需要等待的毫秒數(shù)。下面來(lái)看一個(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 可用于在將來(lái)某個(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í)行到頁(yè)面卸載。以下是一個(gè)常見(jiàn)的使用間歇調(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)用來(lái)實(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);

可見(jiàn),在使用超時(shí)調(diào)用時(shí),沒(méi)有必要跟蹤超時(shí)調(diào)用 ID,因?yàn)槊看螆?zhí)行代碼之后,如果不再設(shè)置另一次超時(shí)調(diào)用,調(diào)用就會(huì)自行停止。一般認(rèn)為,使用超時(shí)調(diào)用來(lái)模擬間歇調(diào)用的是一種最佳模式。在開(kāi)發(fā)環(huán)境下,很少使用真正的間歇調(diào)用,原因是后一個(gè)間歇調(diào)用可能會(huì)在前一個(gè)間歇調(diào)用結(jié)束之前啟動(dòng)。而像前面示例中那樣使用超時(shí)調(diào)用,則完全可以避免這一點(diǎn)。所以,最好不要使用間歇調(diào)用。

系統(tǒng)對(duì)話框

瀏覽器通過(guò) alert()、confirm()prompt() 方法可以調(diào)用系統(tǒng)對(duì)話框向用戶顯示消息。系統(tǒng)對(duì)話框與在瀏覽器中顯示的網(wǎng)頁(yè)沒(méi)有關(guān)系,也不包含 HTML。它們的外觀由操作系統(tǒng)及(或)瀏覽器設(shè)置決定,而不是由 CSS 決定。此外,通過(guò)這幾個(gè)方法打開(kāi)的對(duì)話框都是同步和模態(tài)的。也就是說(shuō),顯示這些對(duì)話框的時(shí)候代碼會(huì)停止執(zhí)行,而關(guān)掉這些對(duì)話框后代碼又會(huì)恢復(fù)執(zhí)行。

第一種對(duì)話框是調(diào)用 alert() 方法生成的。它向用戶顯示一個(gè)系統(tǒng)對(duì)話框,其中包含指定的文本和一個(gè) OK(“確定”)按鈕。通常使用 alert() 生成的“警告”對(duì)話框向用戶顯示一些他們無(wú)法控制的消息,例如錯(cuò)誤消息。而用戶只能在看完消息后關(guān)閉對(duì)話框。

第二種對(duì)話框是調(diào)用 confirm() 方法生成的。從向用戶顯示消息的方面來(lái)看,這種“確認(rèn)”對(duì)話框很像是一個(gè)“警告”對(duì)話框。但二者的主要區(qū)別在于“確認(rèn)”對(duì)話框除了顯示OK按鈕外,還會(huì)顯示一個(gè) Cancel(“取消”)按鈕,兩個(gè)按鈕可以讓用戶決定是否執(zhí)行給定的操作。

為了確定用戶是單擊了OK還是Cancel,可以檢查 confirm() 方法返回的布爾值:true 表示單擊了OK,false 表示單擊了Cancel或單擊了右上角的 X 按鈕。確認(rèn)對(duì)話框的典型用法如下。

if (confirm("Are you sure?")) {
    alert("I"m so glad you"re sure! ");
} else {
    alert("I"m sorry to hear you"re not sure.");
}

最后一種對(duì)話框是通過(guò)調(diào)用 prompt() 方法生成的,這是一個(gè)“提示”框,用于提示用戶輸入一些文本。提示框中除了顯示 OK 和 Cancel 按鈕之外,還會(huì)顯示一個(gè)文本輸入域,以供用戶在其中輸入內(nèi)容。prompt() 方法接受兩個(gè)參數(shù):要顯示給用戶的文本提示和文本輸入域的默認(rèn)值(可以是一個(gè)空字符串)。

如果用戶單擊了 OK 按鈕,則 promp() 返回文本輸入域的值;如果用戶單擊了 Cancel 或沒(méi)有單擊 OK 而是通過(guò)其他方式關(guān)閉了對(duì)話框,則該方法返回 null。下面是一個(gè)例子。

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

綜上所述,這些系統(tǒng)對(duì)話框很適合向用戶顯示消息并請(qǐng)用戶作出決定。由于不涉及 HTML、CSS 或 JavaScript,因此它們是增強(qiáng) Web 應(yīng)用程序的一種便捷方式。

location 對(duì)象

location 對(duì)象提供了與當(dāng)前窗口中加載的文檔有關(guān)的信息,還提供了一些導(dǎo)航功能。事實(shí)上,location 對(duì)象是很特別的一個(gè)對(duì)象,因?yàn)樗仁?window 對(duì)象的屬性,也是 document 對(duì)象的屬性;換句話說(shuō),window.locationdocument.location 引用的是同一個(gè)對(duì)象。location 對(duì)象的用處不只表現(xiàn)在它保存著當(dāng)前文檔的信息,還表現(xiàn)在它將 URL 解析為獨(dú)立的片段,讓開(kāi)發(fā)人員可以通過(guò)不同的屬性訪問(wèn)這些片段。下表列出了 location 對(duì)象的所有屬性。

屬性名 例子 說(shuō)明
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)前加載頁(yè)面的完整URL。而 location 對(duì)象的 toString() 方法也返回這個(gè)值
pathname "/WileyCDA/" 返回URL中的目錄和(或)文件名
port "8080" 返回 URL 中指定的端口號(hào)。如果 URL 中不包含端口號(hào),則這個(gè)屬性返回空字符串
protocol "http:" 返回頁(yè)面使用的協(xié)議。通常是 http: 或 https:
search "?q=javascript" 返回URL的查詢字符串。這個(gè)字符串以問(wèn)號(hào)開(kāi)頭
查詢字符串參數(shù)

雖然通過(guò)上面的屬性可以訪問(wèn)到 location 對(duì)象的大多數(shù)信息,但其中訪問(wèn)URL包含的查詢字符串的屬性并不方便。盡管 location.search 返回從問(wèn)號(hào)到 URL 末尾的所有內(nèi)容,但卻沒(méi)有辦法逐個(gè)訪問(wèn)其中的每個(gè)查詢字符串參數(shù)。為此,可以像下面這樣創(chuàng)建一個(gè)函數(shù),用以解析查詢字符串,然后返回包含所有參數(shù)的一個(gè)對(duì)象:

/*
 * 這個(gè)函數(shù)用來(lái)解析來(lái)自URL的查詢串中的name=value參數(shù)對(duì)
 * 它將name=value對(duì)存儲(chǔ)在一個(gè)對(duì)象的屬性中,并返回該對(duì)象
 * 這樣來(lái)使用它
 *
 * 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è)空對(duì)象
    var query = location.search.substring(1);       // 查找到查詢串,并去掉"? "
    var pairs = query.split("&");                   // 根據(jù)"&"符號(hào)將查詢字符串分隔開(kāi)
    for (var i = 0; i < pairs.length; i++) {        // 對(duì)于每個(gè)片段
        var pos = pairs[i].indexOf("=");            // 查找"name=value"
        if (pos == -1) continue;                    // 如果沒(méi)有找到的話,就跳過(guò)
        var name = pairs[i].substring(0, pos);      // 提取name
        var value = pairs[i].substring(pos + 1);    // 提取value
        value = decodeURIComponent(value);          // 對(duì)value進(jìn)行解碼
        args[name] = value;                         // 存儲(chǔ)為屬性
    }
    return args;                                    // 返回解析后的參數(shù)
}
位置操作

使用 location 對(duì)象可以通過(guò)很多方式來(lái)改變?yōu)g覽器的位置。首先,也是最常用的方式,就是使用 assign()方法并為其傳遞一個(gè) URL,如下所示。

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

這樣,就可以立即打開(kāi)新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 對(duì)象的其他屬性也可以改變當(dāng)前加載的頁(yè)面。下面的例子展示了通過(guò)將 hash、search、hostname、pathnameport 屬性設(shè)置為新值來(lái)改變 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)通過(guò)上述任何一種方式修改URL之后,瀏覽器的歷史記錄中就會(huì)生成一條新記錄,因此用戶通過(guò)單擊“后退”按鈕都會(huì)導(dǎo)航到前一個(gè)頁(yè)面。要禁用這種行為,可以使用 replace() 方法。這個(gè)方法只接受一個(gè)參數(shù),即要導(dǎo)航到的 URL;結(jié)果雖然會(huì)導(dǎo)致瀏覽器位置改變,但不會(huì)在歷史記錄中生成新記錄。在調(diào)用 replace() 方法之后,用戶不能回到前一個(gè)頁(yè)面,來(lái)看下面的例子:




    You won"t be able to get back here

    
    

Enjoy this page for a second, because you won"t be coming back here.

如果將這個(gè)頁(yè)面加載到瀏覽器中,瀏覽器就會(huì)在1秒鐘后重新定向到 shijiajie.com。然后,“后退”按鈕將處于禁用狀態(tài),如果不重新輸入完整的 URL,則無(wú)法返回示例頁(yè)面。

與位置有關(guān)的最后一個(gè)方法是 reload(),作用是重新加載當(dāng)前顯示的頁(yè)面。如果調(diào)用 reload() 時(shí)不傳遞任何參數(shù),頁(yè)面就會(huì)以最有效的方式重新加載。也就是說(shuō),如果頁(yè)面自上次請(qǐng)求以來(lái)并沒(méi)有改變過(guò),頁(yè)面就會(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 對(duì)象

history 對(duì)象保存著用戶上網(wǎng)的歷史記錄,從窗口被打開(kāi)的那一刻算起。因?yàn)?historywindow 對(duì)象的屬性,因此每個(gè)瀏覽器窗口、每個(gè)標(biāo)簽頁(yè)乃至每個(gè)框架,都有自己的 history 對(duì)象與特定的 window 對(duì)象關(guān)聯(lián)。出于安全方面的考慮,開(kāi)發(fā)人員無(wú)法得知用戶瀏覽過(guò)的 URL。不過(guò),借由用戶訪問(wèn)過(guò)的頁(yè)面列表,同樣可以在不知道實(shí)際 URL 的情況下實(shí)現(xiàn)后退和前進(jìn)。

使用 go() 方法可以在用戶的歷史記錄中任意跳轉(zhuǎn),可以向后也可以向前。這個(gè)方法接受一個(gè)參數(shù),表示向后或向前跳轉(zhuǎn)的頁(yè)面數(shù)的一個(gè)整數(shù)值。負(fù)數(shù)表示向后跳轉(zhuǎn)(類似于單擊瀏覽器的“后退”按鈕),正數(shù)表示向前跳轉(zhuǎn)(類似于單擊瀏覽器的“前進(jìn)”按鈕)。來(lái)看下面的例子。

// 后退一頁(yè)
history.go(-1);

// 前進(jìn)一頁(yè)
history.go(1);

// 前進(jìn)兩頁(yè)
history.go(2);

也可以給 go() 方法傳遞一個(gè)字符串參數(shù),此時(shí)瀏覽器會(huì)跳轉(zhuǎn)到歷史記錄中包含該字符串的第一個(gè)位置——可能后退,也可能前進(jìn),具體要看哪個(gè)位置最近。如果歷史記錄中不包含該字符串,那么這個(gè)方法什么也不做,例如:

// 跳轉(zhuǎn)到最近的 shijiajie.com 頁(yè)面
history.go("shijiajie.com");

另外,還可以使用兩個(gè)簡(jiǎn)寫(xiě)方法 back()forward() 來(lái)代替 go()。顧名思義,這兩個(gè)方法可以模仿瀏覽器的“后退”和“前進(jìn)”按鈕。

// 后退一頁(yè)
history.back();

// 前進(jìn)一頁(yè)
history.forward();

除了上述幾個(gè)方法外,history 對(duì)象還有一個(gè) length 屬性,保存著歷史記錄的數(shù)量。這個(gè)數(shù)量包括所有歷史記錄,即所有向后和向前的記錄。對(duì)于加載到窗口、標(biāo)簽頁(yè)或框架中的第一個(gè)頁(yè)面而言,history.length 等于0。通過(guò)像下面這樣測(cè)試該屬性的值,可以確定用戶是否一開(kāi)始就打開(kāi)了你的頁(yè)面。

if (history.length == 0){
    //這應(yīng)該是用戶打開(kāi)窗口后的第一個(gè)頁(yè)面
}

雖然 history 并不常用,但在創(chuàng)建自定義的“后退”和“前進(jìn)”按鈕,以及檢測(cè)當(dāng)前頁(yè)面是不是用戶歷史記錄中的第一個(gè)頁(yè)面時(shí),還是必須使用它。

小結(jié)

BOM(瀏覽器對(duì)象模型)以 window 對(duì)象為依托,表示瀏覽器窗口以及頁(yè)面可見(jiàn)區(qū)域。同時(shí),window 對(duì)象還是 ECMAScript 中的 Global 對(duì)象,因而所有全局變量和函數(shù)都是它的屬性,且所有原生的構(gòu)造函數(shù)及其他函數(shù)也都存在于它的命名空間下。本章討論了下列 BOM 的組成部分。

在使用框架時(shí),每個(gè)框架都有自己的 window 對(duì)象以及所有原生構(gòu)造函數(shù)及其他函數(shù)的副本。每個(gè)框架都保存在 frames 集合中,可以通過(guò)位置或通過(guò)名稱來(lái)訪問(wèn)。

有一些窗口指針,可以用來(lái)引用其他框架,包括父框架。

top 對(duì)象始終指向最外圍的框架,也就是整個(gè)瀏覽器窗口。

parent 對(duì)象表示包含當(dāng)前框架的框架,而 self 對(duì)象則回指 window。

使用 location 對(duì)象可以通過(guò)編程方式來(lái)訪問(wèn)瀏覽器的導(dǎo)航系統(tǒng)。設(shè)置相應(yīng)的屬性,可以逐段或整體性地修改瀏覽器的 URL。

調(diào)用 replace() 方法可以導(dǎo)航到一個(gè)新 URL,同時(shí)該 URL 會(huì)替換瀏覽器歷史記錄中當(dāng)前顯示的頁(yè)面。

navigator 對(duì)象提供了與瀏覽器有關(guān)的信息。到底提供哪些信息,很大程度上取決于用戶的瀏覽器;不過(guò),也有一些公共的屬性(如 userAgent)存在于所有瀏覽器中。

BOM中還有兩個(gè)對(duì)象:screenhistory,但它們的功能有限。screen 對(duì)象中保存著與客戶端顯示器有關(guān)的信息,這些信息一般只用于站點(diǎn)分析。history 對(duì)象為訪問(wèn)瀏覽器的歷史記錄開(kāi)了一個(gè)小縫隙,開(kāi)發(fā)人員可以據(jù)此判斷歷史記錄的數(shù)量,也可以在歷史記錄中向后或向前導(dǎo)航到任意頁(yè)面。

關(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)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/80797.html

相關(guān)文章

  • JavaScript 闖關(guān)

    摘要:對(duì)象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對(duì)象模型是針對(duì)和文檔的一個(gè)。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動(dòng)態(tài)的,根闖關(guān)記之語(yǔ)法的語(yǔ)法大量借鑒了及其他類語(yǔ)言如和的語(yǔ)法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...

    mj 評(píng)論0 收藏0
  • JavaScript 闖關(guān)簡(jiǎn)介

    摘要:瀏覽器只是實(shí)現(xiàn)的宿主環(huán)境之一,其他宿主環(huán)境包括和。年月,版發(fā)布,成為國(guó)際標(biāo)準(zhǔn)。事件定義了事件和事件處理的接口。對(duì)于已經(jīng)正式納入標(biāo)準(zhǔn)的來(lái)說(shuō),盡管各瀏覽器都實(shí)現(xiàn)了某些眾所周知的共同特性,但其他特性還是會(huì)因?yàn)g覽器而異。 JavaScript 是面向 Web 的編程語(yǔ)言,絕大多數(shù)現(xiàn)代網(wǎng)站都使用了 JavaScript,并且所有的現(xiàn)代 Web 瀏覽器(電腦,手機(jī),平板)均包含了 JavaScri...

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

    摘要:本課程之所以叫做闖關(guān)記,是因?yàn)椴糠终鹿?jié)精心設(shè)計(jì)了挑戰(zhàn)關(guān)卡,通過(guò)提供更多的實(shí)戰(zhàn)機(jī)會(huì),讓大家可以循序漸進(jìn)地有目的地有挑戰(zhàn)地開(kāi)展學(xué)習(xí)。課程結(jié)構(gòu)及目錄以下目錄只是初步構(gòu)想,課程結(jié)構(gòu)及內(nèi)容會(huì)根據(jù)實(shí)際情況隨時(shí)進(jìn)行調(diào)整。 為何寫(xiě)作此課程 stone 主要負(fù)責(zé)基于 Web 的企業(yè)內(nèi)部管理系統(tǒng)的開(kāi)發(fā),雖然能夠熟練地使用 JavaScript,但隨著對(duì) JavaScript 的理解越來(lái)越深,才發(fā)現(xiàn)自己尚...

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

    摘要:內(nèi)存回收此時(shí),局部變量就沒(méi)有存在的必要了,因此可以釋放它們的內(nèi)存以供將來(lái)使用。局部變量會(huì)在它們離開(kāi)執(zhí)行環(huán)境時(shí)自動(dòng)被解除引用,如下面這個(gè)例子所示手工解除的引用由于局部變量在函數(shù)執(zhí)行完畢后就離開(kāi)了其執(zhí)行環(huán)境,因此無(wú)需我們顯式地去為它解除引用。 JavaScript 具有自動(dòng)垃圾收集機(jī)制(GC:Garbage Collecation),也就是說(shuō),執(zhí)行環(huán)境會(huì)負(fù)責(zé)管理代碼執(zhí)行過(guò)程中使用的內(nèi)存。而...

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

    摘要:使用元素嵌入代碼時(shí),只需為指定屬性。需要注意的是,帶有屬性的元素不應(yīng)該在其和元素之間再包含額外的代碼。在包含外部文件時(shí),必須將屬性設(shè)置為指向相應(yīng)文件的。所有元素都會(huì)按照他們?cè)陧?yè)面中出現(xiàn)的先后順序依次被解析。關(guān)注,獲取最新動(dòng)態(tài)。 當(dāng)學(xué)習(xí)一門(mén)新的編程語(yǔ)言的時(shí)候,應(yīng)該邊學(xué)邊做,反復(fù)演練以加深理解。因此,你需要一個(gè) JavaScript 解釋器。幸運(yùn)的是,每一個(gè) Web 瀏覽器都包含一個(gè) Ja...

    atinosun 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

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