二刷《高程》第八章BOM筆記整理。 如果要在Web中使用JavaScript,那麼BOM(瀏覽器對象模型)才是真正核心,BOM提供很多對象,用於訪問瀏覽器的功能,這些功能與任何網頁內容無關。 window對象 location對象 navigator對象 screen對象 history對象 win ...
二刷《高程》第八章BOM筆記整理。
如果要在Web中使用JavaScript,那麼BOM(瀏覽器對象模型)才是真正核心,BOM提供很多對象,用於訪問瀏覽器的功能,這些功能與任何網頁內容無關。
- window對象
- location對象
- navigator對象
- screen對象
- history對象
window對象
BOM的核心對象,表示瀏覽器的一個實例,它既是通過JavaScript訪問瀏覽器視窗的一個介面,又是ECMAScript規定的Global對象。這意味著在網頁中定義的任何一個對象,變數和函數都以window作為其Global對象,因此有權訪問parseInt()等全局方法。
(1).全局作用域:拋開全局變數會成為window對象的屬性不談,定義全局變數與在window對象上直接定義屬性還是有點差別:全局變數不能通過delete操作符刪除,而直接在window對象上定義的屬性可以。
var age = 11; window.name = 'xx'; //在<IE9時拋錯,其他所有瀏覽器返回false delete window.age; //false window.age; // 11 //在<IE9時拋錯,其他所有瀏覽器返回true delete window.name; //true window.name; // undefined
原因:當configurable特性被設置為false時候表示不允許通過delete刪除屬性,而直接在對象上定義的屬性它的這個特性為true。
<IE9中的表現是這樣的:
當嘗試訪問未聲明的變數會拋出錯誤,但是通過查詢window對象,可以知道某個可能未聲明的變數是否存在。
var a = b; //拋錯,嘗試訪問未聲明的變數b var a = window.b; //正常,嘗試訪問window.b這是一次屬性查詢到的值是undefiend
Windows Mobile平臺的IE瀏覽器不允許通過window.property = value之類的形式,直接在window對象上創建新的屬性或方法。可是在全局作用域中聲明的所有的變數和函數照樣會變成window對象的成員。
(2).視窗關係及框架:如果頁面中包含框架,則每個框架都擁有自己的window對象,並且保存在frames集合中,可以通過數值索引(從0開始,從左至右,從上到下)或者框架名稱來訪問相應的window對象。
每個window對象都有一個name屬性,其中包含框架的名稱但Chrome下並不能通過主window直接訪問子集框架的window上的屬性(除過個別特殊屬性比如top,parent)這會導致跨域,如下
對於如下頁面:
<html> <head> <title>Frameset Example</title> </head> <frameset rows="160, *"> <frame src="frame.html" name="topFrame"> <frameset cols="50%, 50%"> <frame src="anotherframe" name="leftFrame"> <frame src="yetanotherframe" name="rightFrame"> </frameset> </frameset> </html>
frameset可定義一個框架集,它被用來組織多個視窗的(框架)。每個框架有獨立的文檔,<frameset>標簽不能與<body>標簽一起使用,但<noframes>標簽可放在body中,cols表示框架集中的列的數目和尺寸。rows表示行的數目和尺寸,單位為px,%,*
以上代碼創建了一個框架集,其中一個框架居上,兩個框架居下,可通過window.frames[0]或window.frames["topFrame"]引用上方框架,也可使用top而非window來引用這些框架(如top.frames[0])。
- top對象始終指向最高(最外)層的框架,即瀏覽器視窗(window.top == window),使用它可以確保在一個框架中正確地訪問另一個框架。因為對於在一個框架中編寫的任何代碼來說,其中的window對象指向的都是那個框架的特定實例,而非最高層框架。
//訪問topFrame的window的幾種方式 window.frames[0]; window.frames["topFrame"]; top.frames[0]; top.frames["topFrame"]; frames[0]; frames["topFrame"] //剩下兩個frames的window對象訪問類似
- 與top相對的另一個window對象是parent,parnet(父)對象始終指向當前框架的直接上層框架,某些情況下parent有可能等於top,但在沒有框架情況下,parnet一定等於top(此時它們都等於window)。如下例子:
<html> <head> <title>Frameset Example</title> </head> <frameset rows="100, *"> <frame src="frame.html" name="topFrame"> <frameset cols="50%, 50%"> <frame src="anthorframe.html" name="leftFrame"> <frame src="anotherframeset.html" name="rightFrame"> </frameset> </frameset> </html>
這個框架集中的一個框架rightFrame包含了另一個框架集,該框架集的代碼如下:
<html> <head> <title>Framset Example</title> </head> <frameset cols="50%, 50%"> <frame src="one.html" name="one"> <frame src="two.html" name="two"> </frameset> </html>
瀏覽器在載入完第一個框架後會繼續將第二個框架載入到rightFrame中,在one中訪問parent,那麼就是rightFrame。
在topFrame中,parent指向的是top,因為topFrame的直接上層框架就是最外層框架。
註意除非最高層視窗是通過window.open()打開的,否則其window對象的name屬性不會包含任何值。(??)
- 與框架有關的最後一個對象是self,它始終指向window,實際上,self和window對象可以互換使用。引入self目的只是為了與top和parent對象對應起來,因此它不格外包含其他值。
在使用框架情況下,瀏覽器中會存在多個Global對象,在每個框架中定義的全局變數會自動成為框架中window對象的屬性,由於每個window對象都包含原生類型的構造函數,因此每個框架都有一套自己的構造函數,這些構造函數一一對應但並不相等。top.frames[0].Object!==top.Object,這個問題會影響到對跨框架傳遞的對象使用instanceof操作符。之前有驗證過,見http://www.cnblogs.com/venoral/p/5232676.html
(3).視窗位置:用來操作和修改window對象位置的屬性和方法有很多,除了FF在screenX和screenY屬性中提供相同的視窗位置信息(Safari和Chrome也同時支持這兩個屬性),其他多數瀏覽器提供了screenLeft,screenTop屬性用來表示視窗相對於屏幕屏幕左邊和上邊的位置。跨瀏覽器代碼為:
var leftPos = (typeof window.screenLeft == 'number') ? window.screenLeft : window.screenX; var topPos = (typeof window.screenTop == 'number') ? window.screenTop : window.screenY;
在IE中screenTop和screenLeft保存的是從屏幕上邊和左邊到由window對象表示的頁面可見區的距離,即如果window對象是最外層對象,而且瀏覽器視窗緊貼屏幕最上端(y軸坐標為0),那麼screenTop的值就是位於頁面可見區上方的瀏覽器工具欄的像素高度,在Chrome和FF和Safari中,screenY或screenTop中保存的是整個瀏覽器視窗相對於屏幕的坐標值,即在視窗的y軸坐標為0時返回0。
FF,Safari,Chrome始終返回頁面中每個框架集的top.screenX和top.screenY的值,IE則會給出框架相對於屏幕邊界的精確坐標值。
moveTo和moveBy這兩個方法不適用於框架,只能對最外層的window對象使用。
(4).視窗大小:跨瀏覽器確定一個視窗大小,IE9+,FF,Safari,Opera,Chrome有四個屬性:innerWidth,innerHeight,outerWidth,outerHeight
outerWidth,outerHeight表示瀏覽器視窗本身大小(包括工具欄),innerWidth,innerHeight表示瀏覽器視口大小。
<=IE8沒有取得當前瀏覽器視窗的尺寸的屬性,不過它通過DOM提供頁面可視化區域相關信息。
在IE,FF,Chrome,Safari,Opera中,document.documentElement.clientWidth和document.documentElement.clientHeight中保存了頁面視口的信息。在IE6中這些屬性必須在標準模式下才有效,如果在混雜模式就需通過document.body.clientWidth和document.body.clientHeight取得相同信息。
取得頁面視口的大小:
var pageWidth = window.innerWidth, pageHeight = window.innerHeight; //<=IE8 if(typeof pageWidth != 'number'){ if(document.compatMode == 'CSS1Compat'){ pageWidth = document.documentElement.clientWidth; pageHeight = document.documentElement.clientHeight; }else{ pageWidth = document.body.clientWidth; pageHeight = document.body.clientHeight; } }
對於移動設備,window.innerWidth和window.innerHeight保存著可見視口,即屏幕上可見頁面區域大小。移動IE不支持這些屬性但通過document.documentElement.clientWidth和document.documentElement.clientHeight提供相同信息,隨著頁面縮放這些值也會相應變化。
在其他移動瀏覽器中,document.documentElement度量的是佈局視口,即渲染後頁面的實際大小(與可見視口不同,可見視口只是整個頁面中的一小部分)。移動IE瀏覽器把佈局視口的信息保存在document.body.clientWidth和document.body.clientHeight中,這些值不會隨著頁面縮放而變化(??)。
resizeTo和resizeBy方法不適用於框架只能對最外層window對象使用。
(5).導航和打開視窗:
window.open(url, 視窗目標, 一個特性字元串, 新頁面是否取代瀏覽器歷史記錄中當前載入頁面的布爾值):可以導航到一個特定的url,也可以打開一個新的瀏覽器視窗。通常只需傳遞第一個參數,最後一個參數只在不打開新視窗的情況下使用。第二個參數是已有視窗或框架的名稱,那麼就會在具有該名稱的視窗或框架中載入第一個參數指定的URL
//等同於<a href="http://www.wrox.com" target="topFrame"></a> window.open(“http://www.wrox.com/”, "topFrame");
如果有一個名叫"topFrame"的視窗或框架就會在該視窗或框架載入這個URL,否則就會新建一個視窗並將其命名為”topFrame“,此外第二個參數可以是”_self“,"_parent","_top","_blank"
測試了一下在框架中window.open()會有跨域的限制:
開了本地伺服器試試:主頁面和test.html的功能變數名稱都為localhost
這是之前:
當執行了window.open('test.html', 'two')後:name為”two“的框架內容載入”test.html“,控制台返回"two"的window對象。(我這裡不清楚為什麼這個路徑必須是相對的才能載入”test.html“頁面,執行window.open("localhost:3000/test.html", "two")雖然不會報錯還會返回two的window對象,但two框架就是不會載入新頁面。當加上協議名後才能成功window.open('http://localhost:3000/test.html', 'two')。
- 彈出視窗:如果給window.open()傳遞的第二個參數並不是一個已經存在的視窗或框架,那麼該方法就會根據第三個參數位置上傳入的字元串創建一個新視窗或新標簽頁,如果沒有傳入第三個參數,就會打開一個帶有全部預設設置(工具欄,地址欄, 狀態欄等)的新瀏覽器視窗(或者打卡一個新標簽頁--根據瀏覽器的設置)。在不打開新視窗的情況下會忽略第三個參數。
第三個參數是一個逗號分隔的名值列表設置字元串,表示在新視窗中都顯示哪些特性。
window.open()返回一個新窗體的引用,但Chrome在有第三個參數情況打開新的標簽頁情況下並沒有返回window,而是undefiend。
對於瀏覽器的主視窗,可以調用top.close()在不經用戶允許情況下關閉自己。
新創建的window對象有一個opener屬性,其中保存著打開它的原始視窗對象,這個屬性只在彈出視窗的最外層window對象(top)中有定義,而且指向調用window.open()的視窗或框架。
雖然彈出視窗中有一個指針指向打開它的原始視窗,但原始視窗中並沒有這樣的指針指向彈出視窗,視窗並不跟蹤記錄它打開的彈出視窗,因此只能在必要的時候自己手動實現跟蹤。
有些瀏覽器(如IE8或Chrome)會在獨立的進程中運行每個標簽頁,當一個標簽頁打開另一個標簽頁時,如果兩個window對象需要彼此通信,那麼新標簽頁就不能運行在獨立的進程中,在Chrome中將心創建的標簽頁opener屬性設置為null,即表示在單獨的進程中運行新標簽頁,告訴瀏覽器新創建的標簽頁不需要與打開它的標簽頁通信,因此可以在獨立的進程中運行。標簽頁間的聯繫一旦切斷,將沒法恢復。但在主標簽頁仍然可以訪問w對象上的各種屬性。 - 安全限制:彈出視窗配置方面增加限制。
- 彈出視窗屏蔽程式:多數瀏覽器都內置有彈出視窗屏蔽程式,如果是瀏覽器內置的屏蔽程式阻止的彈出視窗,那麼window.open()可能會返回null。如果是瀏覽器擴展或其他程式阻止的彈出視窗,window.open()通常會拋出一個錯誤,在檢測返回值時對window.open()的調用封裝在一個try-catch塊中。
var blocked = false; try{ var wroxWin = window.open("http://www.baidu.com", "_blank"); if(wroxWin == null){ blocked = true; } }catch(e){ blocked = true; } if(blocked){ console.log("The popup was blocked!"); }
(6).間歇調用和超時調用:
setTimeout():第一個參數可以是一個包含JS代碼的字元串(就和在eval()函數中使用的字元串一樣)但傳遞字元串可能導致性能損失不建議,也可以是一個函數。第二個參數是一個表示等待多長時間的毫秒數,但經過該時間後指定的代碼不一定會執行,JS是一個單線程式的解釋器,因此一定時間只能執行一段代碼,為了控制要執行的代碼,就有一個JS任務隊列,這些任務會按照將它們添加到隊列的順序執行。第二個參數可以理解成告訴JS再過多長時間把當前任務添加到隊列中,如果隊列是空的,那麼添加的代碼會立即執行,如果隊列不為空那麼就要前面的代碼執行完後再執行。
setTimeout和setInterval()會返回一個數值ID,這個ID是計劃執行代碼的唯一標識符,要取消尚未執行的超時調用計劃,可以調用clearTimeout和clearInterval,只要在指定的時間尚未過去之前調用clearTimeout或clearInterval就可以完全取消超時調用(在還沒加到執行隊列中就取消)。超時調用的代碼都是在全局作用域中執行的,因此函數中的this的值在非嚴格模式下指向window對象,嚴格模式下是undefiend(可是經測試嚴格模式下並不是啊仍然會返回window...)。
var num = 0, max = 10, intervalId = null; function incrementNumber(){ num++; //如果執行次數達到了max設定的值,則取消後續尚未執行的調用 if(num == max){ clearInterval(intervalId); console.log('done'); } } intervalId = setInterval(incrementNumber, 500);
var num = 0, max = 10; function incrementNumber(){ num++; if(num == max){ return; }else{ setTimeout(incrementNumber, 500); } } setTimeout(incrementNumber, 500);
可見在設置超時調用時沒必要跟蹤超時調用ID,因為每次執行代碼之後,如果不再設置另一次超時調用,調用就會停止。
(7).系統對話框:與在瀏覽器中顯示的網頁沒有關係,也不包含HTML,它們的外觀由操作系統及(或)瀏覽器設置決定,不是由css決定。通過這幾個方法打開的對話框都是同步和模態的,顯示這些對話框的時候代碼會停止執行,關掉這些對話框後代碼又恢復執行。
alert():顯示一些用戶無法控制的消息,例如錯誤消息。用戶只能在看完消息後關閉對話框。
confirm():確認對話框除了顯示OK按鈕外,還會顯示一個Cancel(取消)按鈕,點擊“確認”返回true,點擊“取消”或右上角的X按鈕返回false
prompt(str1, str2):提示框,用於提示用戶輸入文本,提示框中除了顯示OK和Cancel按鈕之外,還會顯示一個文本輸入域,以供用戶在其中輸入內容。兩個參數:要顯示給用戶的文本提示和文本輸入域的預設值(可以是一個空字元串)。點擊“確定”返回用戶所填的字元串(如果沒填則返回""),點擊“取消”或右上角的X按鈕返回null。
下麵兩個對話框方法是非同步顯示的,Chrome的對話框計數器不會將它們計算在內,所以它們也不會受用戶禁用後續對話框顯示的影響。
print():顯示列印對話框,會調出瀏覽器自帶的列印的程式。
find():顯示查找對話框。
Location對象
提供與當前視窗載入的文檔有關的信息,還提供了一些導航功能。它既是window對象的屬性又是document對象的屬性(只能說window.location和document.location指向的是同一個對象,即location對象)。location對象的用戶不只表現在它保存著當前文檔的信息,還表現在它將URL解析為獨立的片段,讓開發人員可以通過不同的屬性訪問這些片段。
原型鏈繼承關係為:window.location.__proto__->Location.prototype->Object.prototype
hash:返回URL中的hash(#後跟零或多個字元),如果URL不包含散列,則返回空字元串。
host:返回伺服器名稱和埠號(如果有)
hostname:返回不帶埠號的伺服器名稱
href:返回當前載入頁面的完整URL,location.toString()也返回這個。
pathname:返回URL中目錄和(或)文件名
port:返回URL中指定的埠號,如果URL中不包含埠號,則這個屬性返回空字元串。
protocol:返回頁面使用的協議,通常是http:或https:
search:返回URL查詢字元串,這個字元串以問號開頭
(1).查詢字元串參數:解析查詢字元串,返回包含所有參數的一個對象
function getQueryStringArgs(){ var argdecos = {}; //取得查詢字元串並去掉開頭問號 var qs = location.search.length > 0 ? location.search.substring(1) : ""; //取得每一項 var items = qs.length ? qs.split("&") : [], item = null, name = null, value= null, i=0, len = items.length; for(i= 0; i< len; i++){ item = items[i].split("="); name = decodeURIComponent(item[0]); value = decodeURIComponent(item[1]); if(name.length){ args[name] = value; } } return args; }
(2).位置操作
location對象可以通過很多方式來改變瀏覽器位置
assign(url):可以打開新URL併在瀏覽器的歷史記錄中生成一條記錄,如果是將location.href或window.location設置為一個URL值,也會以該值調用assign()方法。
window.location = "http://www.baidu.com"; location.href = "http://www.baidu.com"; //常用 //等價於 location.assign("http://www.baidu.com");
修改location對象的其他屬性也可以改變當前載入的頁面,通過將hash,search,hostname,pathname,port屬性設置為新值來改變URL,每次修改location的屬性(hash除外),頁面都會以新的URL重新載入。
在IE8,FF1,Safari2+,Opera9+,Chrome中,修改hash值會在瀏覽器歷史記錄中生成一條新紀錄,在IE早期版本中,hash屬性不會在用戶單擊”後退“,”前進“按鈕時被更新,只會在用戶單擊包含hash的URL時才會更新。
當通過上述任何一種方式修改URL後,瀏覽器歷史記錄會生成一條新紀錄,因此用戶通過單擊”後退“按鈕都會導航到前一個頁面。要禁用這種行為,可以使用replace(url)方法,參數是要導航到的URL,結果雖然會導致瀏覽器位置改變,但不會在歷史記錄中生成新紀錄,在調用replace方法後用戶不能回到前一個頁面(即使後退按鈕沒有被禁用,但點擊後回到的是被調用replace方法的那個頁面的上一個頁面)。
reload():重新載入當前顯示頁,不傳參數頁面會以最有效的方式重新載入,即如果頁面自上次請求以來並沒有改變過,頁面就會從瀏覽器緩存中重新載入。如果要強制從伺服器重新載入,需要給參數傳遞true(經測試也沒有效果呀..仍舊是304??)。
位於reload後面的代碼有可能會也可能不會執行,這要取決於網路延遲或系統資源等因素。Chrome下測試是先運行後面的代碼再執行reload。
navigator對象
識別客戶端瀏覽器,navigator對象是所有支持JS瀏覽器所共有的,IE中window.clientInformation和Opera中的window.opera。
Chrome和IE中window.clientInformation == window.navigator,FF沒有該屬性。
navigator.__proto__ -> Navigator.prototype -> Obeject.prototype
navigator.appCodeName:瀏覽器名稱,通常都是Mozilla,即使在非Mozilla瀏覽器中也是如此。
navigator.userAgent:瀏覽器用戶代理字元串,chrome為:
"Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36"
(1).檢測插件:在非IE中可以使用navigator.plugins(並不是說IE不能訪問navigator.plugins,能訪問但返回的對象length屬性為0),返回PluginArray類型的實例。
navigator.plugins.__proto__ -> PluginArray.prototype -> Object.prototype
plugins集合可以繼承refresh(arg)方法,用於刷新plugins以反映最新安裝的插件,參數arg表示是否應該重新載入頁面的一個布爾值,true為重新載入包含插件的所有頁面,否則只更新plugins集合不重新載入頁面。
navigator.plugins的每一項是Plugin類型的實例,
navigator.plugins.__proto__ -> Plugin.prototype -> Object.prototype
name:插件的名字
description:插件的描述
filename:插件的文件名
length:插件所處理的MIME類型的數量
在檢測插件時需要迴圈迭代每個插件並將插件的name與給定名字進行比較:
function hasPlugin(name){ name = name.toLowerCase(); for(var i=0; i<navigator.plugins.length; i++){ if(navigator.plugins[i].name.toLowerCase().indexOf(name) > -1) return true; } return false; }
navigator.mimeTypes:在瀏覽器中註冊的MIME類型數組,是MimeTypeArray類型實例對象
navigator.mimeTypes.__proto__ -> MimeTypeArray.prototype -> Obejct.prototype
navigator.mimeTypes的每一項都是MimeType類型的實例
navigator.mimeTypes[0].__proto__ -> MimeType.prototype -> Obejct.prototype
description:MIME類型描述
enabledPlugin:回指插件對象
suffixes:與MIME類型對應的文件擴展名字元串
type:完整MIME類型字元串的type
檢測IE中插件:因為IE不支持Netspace式的插件,在IE中檢測插件的唯一方式就是使用專有的ActiveXObejct類型,並嘗試創建一個特定插件的實例,IE是以COM對象的方式實現插件的,而COM對象使用唯一標識符來標識的,因此想要檢測特定插件就必須知道其COM標識符,Flash的標識符是ShockwaveFlash.ShockwaveFlash,知道唯一標識符後就可以編寫類似下麵函數來檢測IE中是否安裝相應插件:
function hasIEPlugin(name){ try{ new ActiveXObject(name); return true; }catch(ex){ return false; } } hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
hasIEPlugin("QuickTime.QuickTime");
鑒於IE和非IE檢測插件方法差別太大,因此典型做法就是針對每個插分別創建檢測函數:
//檢測所有瀏覽器的Flash function hasFlash(){ var result = hasPlugin("Flash"); if(!result){ result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash"); } return result; } //檢測所有瀏覽器QuickTime function hasQuickTime(){ var result = hasPlugin("QuickTime"); if(!result){ result = hasIEPlugin("QuickTime.QuickTime"); } return result; }
(2).註冊處理程式:
FF2為navigator對象新增了registerContentHandler()和registerProtocolHandler()方法(這兩方法在H5中定義的),可以讓一個站點指明它可以處理特定類型的信息。隨著RSS閱讀器和線上電子郵件程式興起,註冊處理程式就為像使用桌面應用程式一樣預設使用這些線上應用程式提供了一種方式。
registerContentHandler(要處理的MIME類型, 可以處理該MIME類型的頁面URL, 應用程式名稱):比如將一個站點註冊為處理RSS源的處理程式
navigator.registerContentHandler("application/rss+xml", "http://www.somereader.com?feed=%s", "Some Reader");
第一個參數是RSS源的MIME類型,第二個參數是應該接收RSS源URL的URL,其中%s表示RSS源URL,由瀏覽器自動插入,當下次請求RSS源時,瀏覽器就會打開指定的URL,而相應的web應用程式將以適當方式來處理該請求。
<=FF4版本只允許在registerContentHandler()方法中使用單個MIME類型:application/rss+xml,application/atom+xml,application/vnd.mozilla.maybe.feed,這三個MIME類型作用都一樣即為RSS或ATOM新聞源(feed)註冊處理程式。
registerProtocolHandler(要處理的協議例如mailto或ftp, 處理該協議的頁面的URL, 應用程式名稱)方法:將一個應用程式註冊為預設的郵件客戶端,該例子註冊了一個mailto協議的處理程式,該程式指向一個基於web的電子郵件客戶端,第二個參數仍然是處理相應請求的URL,%s表示原始的請求。
navigator.registerProtocolHandler("mailto", "http://www.someemailclient.com?cmd=%s", "Some Mail Client");
screen對象
表明客戶端的能力,包括瀏覽器視窗外部的顯示器信息,如像素寬度和高度等。每個瀏覽器中的screen對象都包含著各不相同的屬性
screen.__proto__ -> Screen.prototype -> Obeject.prototype
screen.availWidth:屏幕的像素寬度減系統部件寬度之後的值
screen.avaliHeight:屏幕的像素高度減系統部件高度之後的值
screen.avaliLeft:未被系統部件占用的最左側的像素值
screen.avaliTop:未被系統部件占用最上方的像素值
height:屏幕的像素高度
width:屏幕的像素寬度
history對象
保存用戶上網歷史記錄,從視窗被打開那一刻算起。因為history是window對象的屬性,因此每個瀏覽器視窗,每個標簽頁乃至每個框架都有自己的history對象與特定的window對象關聯。處於安全考慮開發人員無法得知用戶瀏覽過的URL,但可以藉助用戶訪問過的頁面列表,同樣可以在不知道實際URL的情況下實現後退和前進。
雖然不常用,但在創建自定義的”後退“和”前進“按鈕,檢測當前頁面是不是用戶歷史記錄中的第一個頁面還得用。
history.__proto__ -> History.prototype -> Object.prototype
length:保存著歷史記錄的數量,包括所有歷史記錄,所有向前和向後的記錄。對於載入到視窗,標簽頁或框架中的第一個頁面而言,history.length等於0,可用此來判斷用戶是否一開始就打開了你的頁面。
history.go(args):在用戶的歷史記錄中任意跳轉,可向前也可向後,參數為向前或向後跳轉頁面數的一個整數值。負數表示向後跳轉(類似單擊瀏覽器後退按鈕),正數表示向前跳轉(類似單擊瀏覽器前進按鈕),參數也可以是字元串,此時瀏覽器會跳轉到歷史記錄中包含該字元串的第一個位置——可能後退,也可能前進,具體要看哪個位置更近。如果記錄中不包含該字元串,什麼也不做。
history.go("baidu.com"); //調到最近的”baidu.com“頁面
history.back():後退一頁
history.forward(): 前進一頁
當頁面URL改變時,就會生成一條歷史記錄,包括hash的變化
參考
《JavaScript高級程式設計》