JavaScript權威指南--window對象

知識要點

window對象及其客戶端javascript所扮演的核心角色:它是客戶端javascript程序的全局對象。本章介紹window對象的屬性和方法,這些屬性定義了不一樣的API,可是隻有一部分實際上和瀏覽器窗口相關。window對象是以窗口命名的javascript

1.計時器

setTimeout()和setIterval()能夠用來註冊在指定的時間以後單次或重複調用的函數。由於它們都是客戶端javascript中的重要全局函數,因此定義爲window對象方法,但做爲通用函數,其實並不會對窗口作什麼事情。html

window對象的setTimeout()方法用來實現一個函數在指定的毫秒後運行。setTimeout返回一個值,這個值能夠傳給clearTimeout()用於取消這個函數的執行。html5

/**定時器應用函數
 * 安排函數f()在將來的調用模式
 * 在等待了若干時間後調用f()
 * 若是設置了interval並無設置end參數,則f()的調用不會中止
 * 只有制定了f(),纔會從start=0時刻開始
 * 注意,調用invoke()不會阻塞,會當即返回
 * */
function invoke(f, start, interval, end) {
    if (!start) start = 0;//默認設置爲0
    if(arguments.length <=2)//單次調用模式
    setTimeout(f,start);//start秒後調用f
    else{      //屢次調用模式
        setTimeout(repeat,start);//若干秒後調用repeat()
        function repeat(){
            var h = setInterval(f,interval);//循環調用f()
            //在end結束後調用,嵌套是end已經定義了
            if(end) setTimeout(function(){clearInterval(h);},end);
        }
    }
}

談談setTimeout()和setInterval()問題java

因爲歷史緣由,setTimeout()和setInterval()第一個參數能夠做爲字符串傳入。若是這麼作,那這個字符串會在指定的超時時間或間隔以後求值(至關於執行eval()).除了前兩個參數以外,HTML5規範還容許setTimeout()和setInterval()傳入額外的參數,而且在調用函數的時候把這些參數傳遞過去。然而,若是須要支持IE的話,就不要應用此特性了。web

若是以0毫秒時間調用setTimeout,那麼指定的函數不會馬上執行。相反會把它放到隊裏中,等到前面處於等待狀態的事件處理程序徹底完成以後,再馬上調用它。正則表達式

補充:chrome

function parent(){   
    function child(){   
        setTimeout(child2(),1000);   
        setTimeout(parent2(),1000);   
        alert("use child1")   
        }   
    function child2(){   
        alert("use child2")   
        }   
    child();   
    }   
parent();//調用parent
function parent2(){   
    alert("I’m your mather")   
    } 

輸出:直接按順序輸出:2-1-l`m。給第一個參數添加雙引號成爲字符串便可。小程序

function parent(){   
    function child(){   
        setTimeout("child2()",1000);   
        setTimeout("parent2()",1000);   
        console.log("use child1")   
    }   
    function child2(){   
        console.log("use child2")   
    }   
    child();   
}   
parent();//調用parent
function parent2(){   
    console.log("I’m your mather")   
}   

輸出結果:segmentfault

這說明setTimeout只能訪問全局對象的屬性和方法,而不能訪問私有做用域內的屬性和方法。其實setTimeout是個window對象的一個方法,f是做爲window對象的一個方法調用的,其效果就像一個<script>標籤裏面的代碼同樣只能訪問,對於函數裏面的變量和方法是沒法訪問的。這就是爲何建議使用函數代替字符串的一個緣由。另外,傳遞字符串也有可能致使性能損失。數組

2.瀏覽器的定位和導航

window對象的location屬性引用的是Location對象,它表示該窗口中當前顯示的文檔的URL,並定義了方法使窗口載入新的文檔。

Document對象的location屬性也引用到Location對象:

window.location === document.location; //=>true 老是返回true

Document對象也有一個URL屬性,是文檔首次載人後保存該文檔的URL靜態字符串。若是定位到文檔中的片斷標識符(如#table-of-contens),Location對象會作相應的更新,而document.url屬性卻不會改變。

2.1.解析url

window對象的location屬性引用是Location對象,表示該窗口當前顯示的的文檔的URL。Location對象的href屬性是一個字符串,包含URL的完整文本。Location對象的toString()方法返回href屬性的值,所以會在隱式調用toString()狀況下,使用location代替location.href。

var d = location.href;
var c = location.toString();
console.log(d === c)

這個對象的其它屬性,protocol,host,hostname,port,pathname和search分別表示URL的各個部分。它們稱爲"URL分解",同時被Link對象(經過HTML文檔中的a和<area>元素建立)支持,參閱本書的第四部分,Location和Link項獲取詳細信息。

Location對象的hash和seerch比較有趣。若是有的話,hash表示URL中的「片斷標識符 #xx」部分,search返回問號以後的URL,這部分一般是某種類型的查詢字符串。通常來講這部份內容是用來參數化URL並在其中嵌入參數的。經常使用於運行在服務器上的腳本,但在啓動JavaScript的頁面中也可使用。

下面的例子展現了一個通用函數urlArgs()定義,能夠用這個函數將參數從URL的search屬性中提取出來。該例子用到了decodeURIComponent(),後者是在客戶端Javascript定義的全局函數(參加本書第三章部分中的Global獲取詳細內容)。

/**
 *這個函數來解析來自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('=');
        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;
}

2.2.載入新的文檔

Location對象的assign()方法可使窗口載入並顯示你指定的url中的文檔。replace()方法也相似,但它在載入新的文檔以前會從瀏覽歷史把當前文檔刪除。若是腳本無條件的載入一個新的文檔,replace()方法是可能比assgin()方法更好的選擇。不然,後退按鈕會使用瀏覽器帶回原始文檔。而相同的腳本則會再次載入新文檔。若是檢測到用戶瀏覽器不支持某些特性來顯示功能齊全的版本,能夠用location.replace()來載入靜態的HTML版本:

 //若是瀏覽器不支持XMLHttpRequest對象
 //則將其重定向到一個不須要Ajax的靜態頁面
if (!XMLHttpRequest) location.replace("staticpage.html");

注意,在這個例子中傳入replace()的是一個相對URL。相對URL是相對於當前頁面所在的目錄來解析的,就像將它們用於一個超連接中。

除了assign()和replace()方法,Location對象還定義了reload()方法,後者可讓瀏覽器從新載入當前文檔。

使瀏覽器跳轉到新頁面的一種更傳統的方法是直接賦值給location

location = "https://segmentfault.com/";

也可用相對URL,它會對其進行解析:

location = "page.html";

純粹的片斷標識符也是url的一種類型,它不會讓瀏覽器載入新文檔,但只會使它滾動到文檔的某個位置。#top標識符是一個特殊例子:若是文檔沒有元素額ID是"top",它會讓瀏覽器跳轉到文檔開始處。

location = "#top";

Location對象的URL分解屬性是可寫的,對它們從新賦值會改變URL的位置,而且致使瀏覽器載入一個新的文檔(若是改變的是hash屬性,則在當前文檔中進行跳轉):

location.search = "?page=" + (pagename+1);//載入新的頁面

3.瀏覽歷史

window對象的history屬性引用的是該窗口的History對象。History對象是用來把窗口的瀏覽歷史用文檔和文檔狀態列表的形式表示。History對象的length屬性表示瀏覽歷史列表中的元素數量,處於安全考慮,腳本不能訪問已經保存的URL(若是容許那任意腳本均可以窺探瀏覽歷史)。

history對象的back()和forward()方法與瀏覽器的「後退」和「前進」按鈕同樣。第三個方法go()接受一個參數,能夠在歷史列表向前(正參數)向後(幅參數)跳過任意個頁面。

history.go(-2); //向後兩個歷史記錄,至關於後退按鈕兩次

若是窗口包含多個子窗口(好比iframe見14.8.2節),子窗口的瀏覽歷史會按時間順序穿插在主窗口的歷史中。這意味着在主窗口調用history.back()可能會致使其中一個子窗口往回跳到前一個顯示文檔,但主窗口保留當前狀態不變。

現代的web應用能夠不經過載入新的文檔而動態的改變自身內容(1五、18章)。這麼作可能但願用戶能用「後退」和「前進」按鈕在這些動態建立應用狀態之間跳轉。html5將這些技術標準化(22章2節)。

HTML5以前的歷史管理是個更復雜的難題。應用程序必需要在窗口瀏覽歷史中建立一個新的條目來管理自身的歷史記錄。。。。。。

在實際的工做中,那些須要之前的HTML5歷史管理的項目中,開發者會使用一些現成 解決方法,不少框架都實現了這些功能。例如jQuery的history插件。也有一些單獨的管理歷史記錄的類庫。RSH(Really Simple History)是其中一個比較流行的示例。(22章2節會有關於html5的歷史管理)

4.瀏覽器和屏幕信息

本節介紹window對象的navigator和screen屬性,它們分別引用的是Navigator和Screen對象,這些對象信息容許腳本根據環境定製的行爲。

4.1.Navigator對象

window對象的navigator屬性引用的是包含瀏覽器廠商和版本信息的Navigator對象。

這樣命名是爲了記念Netscape以後Navigator瀏覽器。

過去會用其來肯定腳本是在哪一種瀏覽器運行,如今瀏覽器種類繁多,也有一種更好的功能測試方法(13.4.3節)。可是Navigation仍是有價值的,在這種狀況下有用:當須要解決存在於某個特定的瀏覽器的特定版本中的特殊的bug時。

可使用這些屬性進行瀏覽器嗅探:

  • appName:web瀏覽器的全稱,IE中,它顯示「Microsoft Internet Exploer」.在firefox中,該屬性就是「Netscape」,在其它瀏覽器中也是(爲了兼容如今的瀏覽器嗅探碼)。
  • appVersion:此屬性一般以數字開始,並跟隨瀏覽器開發商和版本信息等詳細字符串。字符串的前邊一般是4.0或者5.0,表示它是第4仍是第5代兼容的瀏覽器。appVersion沒有標準格式。全部沒有辦法判斷瀏覽器的類型
  • userAgent:瀏覽器在它的User-Agent HTTP頭部發送的字符串。這個屬性一般包含全部appVersion信息,而且經常包含其它細節。和appVersion同樣,它也沒有標準格式。因爲這個屬性包含絕大部分信息,所以,瀏覽器嗅探代碼一般使用它。
  • platform:在其上運行的瀏覽器的操做系統(多是硬件的字符串)。
navigator.appName
//不是Navigator.appName,屬性是引用Navigator對象

Navigator屬性的複雜性正說明了瀏覽器嗅探對於處理客戶端兼容性問題是沒有太大幫助的。appName(都設爲Netscape)和appVersion(有起始數字)沒太大意義,因此使用更復雜的userAgent。

下面的例子展現了使用正則表達式(來自jQuery)從navigator.userAgent抽取瀏覽器的版本和名稱方法代碼。

 /* 使用naVigator.userAgent來進行瀏覽器嗅探  */
 //爲客戶端嗅探定義browser.name和browser.version,這裏使用了jQuery1.41的代碼
 //name和number都是字符串,對瀏覽器的輸出結果不同,檢測的結果以下
 //'webkit':safari或chrome,版本號是WebKit的版本號
 //'opera' Opear 版本號就是軟件的把嫩好
 //"mozilla" Firefox或者基於gecko內核的瀏覽器,版本號是Gecko的版本
 //msie     IE+版本號
var browser = (function() {
            var s = navigator.userAgent.toLowerCase();
            var match = /(webkit)[ \/]([\w.]+)/.exec(s) ||
                /(opera)(?:.*version)?[ \/]([\w.]+)/.exec(s) ||
                /(msie)([\w.]+)/.exec(s) ||
                !/compatible/.test(s) && /(mozilla)( ? : .* ? rv : ([\w.] + )) ? /.exec(s)||[];
        return{name:match[1]||"",version:match[2]||"0"};
}());

除了瀏覽器廠商和版本信息的屬性以外,Navigator對象還包含一些雜項屬性和方法。如下是一些標準化的屬性以及普遍應用但未標準的屬性:

  • OnLine:navigator.onLine是表示瀏覽器是否鏈接到網絡。應用:判斷離線的話就保存狀態到本地(20章)
  • geolocation:navigator.geolocation對象擁有肯定用戶地址位置信息的接口,參加22.1章節細節
  • javaEnabled():navigator.javaEnabled是一個非標準的方法,當瀏覽器能運行java小程序時返回true
  • cookieEnabled():navigator.cookieEnabled也是一個非標準方法,若是瀏覽器能夠永久保存cookie時,返回true,而cookie配置「視具體狀況而定」時,可能會返回不正確的值。

4.2.Screen對象。

window對象的screen屬性引用的是Screen對象。它提供有關窗口的大小和可用的顏色數量的信息屬性width和heigth指定的是以像素爲單位的窗口大小,屬性availWidth和availHeiht指是實際可用的顯示大小,它們排除了像桌面任務欄這樣的特性所佔用的空間。屬性colorDepth指定的是顯示的BPP(bits-per-pixel)值,典型的值有16,24,32

window.screen屬性和它引用的screen對象都是非標準但普遍實現的。能夠用Screen對象來肯定web應用是否運行在一個小的屏幕設備上,若是屏幕有限,可能要選用更小的字體和圖片等。

5.對話框

window對象提供了3個方法向用戶顯示簡單的對話框,alert()向用戶顯示一條信息並等待用戶關閉對話框,confirm()要求用戶單擊肯定或取消,返回一個布爾值,prompt()一樣也顯示一條消息,等待用戶輸入字符串,並返回那個字符串。下面的代碼全用了這三種方法:

do {
    var name = prompt("你的名字");
    var correct = confirm("你輸入了" + name + "\n" + "oK確認,chancel取消");
} while (!correct)
 alert("hello " + name);

儘管alert(),confirm()和prompt()都容易使用,可是良好的設計仍是須要有節制的使用它們。現在,惟一常見的就是使用它們調試,查看變量輸出的結果是什麼。

注意,這些對話框中顯示的文本是純文本,而不是HTML格式的文本,只能使用空格,換行符和各類標點符號來格式化這些對話框。

confirm()和prompt()都會產生阻塞,也就是說,在用戶關掉它們所顯示的對話框以前,它們不返回,代碼會中止運行或載入,直到用戶響應爲止。在大多數瀏覽器裏,alert()也會產生阻塞,並等待用戶關閉對話框,但不老是這樣,完整的的細節請參考第四部分的Window.alert()/Window.confirm()、和window.prompt()方法。

除了window的alert()、confirm()和prompt()方法,還有更復雜的方法showModalDialog(),顯示一個包含HTML格式的模態對話框(顯示出來就不能夠點選位於其下面的對話框),能夠給它傳入參數,以及從對話框裏返回值。第一個參數用以指定提供對話框HTML內容的URL,第二個參數是一個任意值(數組和對象都可),這個值在對話框裏的腳本中能夠經過window.dailogArguments屬性的值訪問。第三個參數是一個非標準的列表,包含以分號隔開的name=value對,若是提供了這個參數,能夠配置對話框的尺寸和其餘屬性,用dialogwidth和dialogheight來設置對話框窗口的大小。用resizable=yes來容許用戶改變窗口大小。

這個方法直到窗口關閉以前不會反悔。當窗口關閉後,window.returnValue屬性的值就是此方法的返回值。對話框的HTML內容每每必須包含用來設置returnValue的「確認」按鈕,若是須要則調用window.close(14.8.1節)。

下面的例子是一個適用於showModalDialog()的html文件,代碼頂部註釋包含調用showModalDialog()的樣例。對話框裏顯示的大量文本都來自showModalDialog()第二個參數,而不是寫死在html中。

。。。。。。

6.錯誤處理

window對象的onerror屬性是一個事件處理程序,當未捕獲的異常傳播到調用棧上時就會調用它,並把錯誤消息輸出到瀏覽器的javascript控制檯上若是給這個屬性賦值一個函數,那麼只要這個窗口中發生了javascript錯誤,就會調用該函數,即它成爲了窗口的錯誤處理程序。

因爲歷史緣由,window對象的onerror事件處理函數的調用經過三個字符串參數,而不是經過傳遞一個事件對象。(其它客戶端對象的onerror處理程序所須要的錯誤條件是不同的,可是它們都是正常的事件處理程序,向這個函數只需傳入一個事件對象。)window.onerror的第一個參數是描述錯誤的一條消息。第二個參數是一個字符串,它存放引起錯誤的javascript代碼所在文檔的 url.第三個參數是引起錯誤的行數。

除了這三個參數外,onerror處理程序的返回值也很重要。若是onerror處理程序返回false,它通知瀏覽器事件處理程序已經處理了錯誤,不須要其餘操做。換句話說,瀏覽器不該該顯示它本身的錯誤消息。遺憾的是,因爲歷史緣由,Firefox裏的錯誤程序必須返回true表示它已經處理了錯誤

onerror處理程序是很早期的javascript產物,那時候語言核心不包含try/catch異常處理語句。如今的代碼已經不多使用它。可是在開發階段,你可能須要定義一個錯誤處理程序,當錯誤發生時,來顯式的通知你。

//在一個對話框中彈出錯誤消息,但不超過3次
window.onerror = function(msg, url, line) {
    if(onerror.num++ < onerror.max){
        alert("出錯了:\n" + msg + "\n 地址:" + url + "\n行號:" + line);
        return true; //屏蔽系統事件
    }
}
onerror.max = 3;
onerror.num = 0;

示例:

<html>
<head>
<script type="text/javascript">
onerror=handleErr
var txt=""

function handleErr(msg,url,l)
{
txt="本頁中存在錯誤。\n\n"
txt+="錯誤:" + msg + "\n"
txt+="URL: " + url + "\n"
txt+="行:" + l + "\n\n"
txt+="點擊「肯定」繼續。\n\n"
alert(txt)
return true
}

function message()
{
ablert("Welcome guest!")
}
</script>
</head>

<body>
<input type="button" value="查看消息" onclick="message()" />
</body>

</html>

7.做爲window對象屬性的文檔元素

若是在HTML文檔中使用id屬性來爲元素命名,而且若是window對象沒有此名字的屬性,window對象會賦予一個屬性,它的名字是id屬性的值,而他們的值指向表示文檔元素的HTMLElement對象。

//文檔中存在id="doc"的HTML元素
window.doc

在客戶端javascript中,window對象是以全局對象的形式存在於做用域鏈的最上層,這就意味着在html文檔中使用的id屬性會成爲被腳本訪問的全局變量。若是一個文檔包含<button id="okay"></button>元素,能夠經過全局變量okay引用此元素。

可是:有一個很重要的警告!若是window對象已經具備此名字的屬性,這就不會發生。好比id是history,location或navigator的元素,就不會以全局變量的形式出現,由於這些id已經被佔用了。一樣,若是html文檔包含一個id爲「x」的元素,而且還在代碼中聲明並賦值給全局變量x,那麼顯式聲明的變量會隱藏隱式的元素變量。若是腳本中的變量聲明出如今命名元素以前,那這個變量的存在就會阻止元素獲取它的window屬性。而若是腳本中的變量聲明出如今命名元素以後,那麼變量的顯式賦值就會覆蓋該屬性的隱式值。

15章2節中,你會學到經過document,getElementById()方法,用HTML的id屬性來查找文檔元素。見下面的例子:

var ui = ["input", "prompt", "heading"]; //數組中存放要查找的元素id
ui.forEach(function(id) { //用每一個id查找對於的元素
    ui[id] = document.getElementById(id); //將其存放在一個屬性中
});

運行完這段代碼以後,ui.input,ui.prompt和ui.heading會引用文檔元素。腳本能夠用全局變量input和heading來代替ui.input和ui.heading
但記得14.5節裏window對象有個方法的名字是prompt(),所用腳本中不能用全局變量prompt代替ui.prompt。

元素的id做爲全局變量的隱式應用是web瀏覽器演化過程當中遺留的怪癖。它主要是出於與已有web頁面向後兼容性的考慮。但這裏並不推薦這種作法---瀏覽器廠商能夠在任什麼時候候爲window對象定義新屬性,而這些新屬性都會破壞使用了此屬性名的隱式定義的代碼。反之,用document.getElementById()來顯式查找元素,若是給他一個更簡單的名字,這種用法會更加簡單:

var $ = function(id) {
    return document.getElementById(id);
};
ui.prompt = $("prompt")

假設ID並無被window對象使用的話,那麼任何有id屬性的html元素都會變成全局變量的值。如下HTML元素若是有name屬性的話,也會這樣表現:

<a> <applet> <area> <embed> <form> <frame> <frameset> <img> <object>

id元素在文檔中必須是惟一的,兩個元素不能有相同的id。可是這對name屬性無效。若是上面的元素有多於一個相同的name屬性(或者一個元素有name屬性,而另一個元素有相同值的id屬性),具備該名稱的隱式全局變量會引用一個類數組對象,這個類數組對象的元素是全部命名的元素。

有name或id屬性的<iframe>元素是個特殊的例子。爲它們隱式建立的變量不會引用表示元素自身的Element對象,而是引用表示<iframe>元素建立的嵌套的window對象。本文14.8.2節會討論到它。

8.多窗口和窗體

一個web頁面窗口可能在桌面上包含多個標籤頁。每個標籤 頁都是獨立的「瀏覽上下文」(browsing context),每個上下文都有獨立的window對象,並且相互之間互不干擾

可是窗口不老是和其它窗口徹底沒有關係。一個窗口或標籤頁中的腳本能夠打開新的窗口或標籤頁,當一個腳本這樣作時,這樣多個窗口或窗口與另外一個窗口文檔之間就能夠互操做。(13.6.2節講解的同源策略約束)。本節1小節會介紹窗口的打開和關閉的更多內容。 

html文檔常用<iframe>來嵌套多個文檔。由它所建立的嵌套瀏覽上下文是用它本身的window對象所表示的。廢棄的<frameset>和<frame>元素一樣建立了一個嵌套的瀏覽上下文。每個<frame>都由一個獨立的window對象表示。對於客戶端javascript來講,窗口、標籤頁、iframe和框架都是獨立的瀏覽上下文。對於javascript來講,它們都是window對象。和相互獨立的標籤頁不一樣,嵌套的瀏覽上下文之間並非相互獨立的。在一個窗體中運行javascript程序老是能看見它的祖先和子孫窗體,儘管腳本查看這些窗體中的文檔受到同源策略限制。14.8.2節。

由於window是客戶端javascript的全局對象,每一個窗口或窗體都包含獨立的javascript執行上下文。不過在一個窗口中的javascript代碼,若有同源策略的限制,則可使用另一個窗口中定義的對象、屬性和方法。與此相關的細節會在14.8.3節詳細討論。因爲同源策略的限制致使窗口之間沒法直接交互時,html5提供了一個基於事件的消息傳輸API,能夠用於間接通訊。22章3節會討論。

8.1.打開和關閉窗口

使用window對象的open()方法能夠打開一個新的瀏覽器窗口(或標籤頁,這一般和瀏覽器的配置項有關)。window.open()載入指定的url到新的或已存在的窗口中,並返回表明那個窗口的window對象。它有四個可選的參數。

open()第一個參數是要在新窗口中顯示的文檔的url。若是省略(也能夠是空字符串),那麼會使用頁面的URLabout:blank。

opne()第二個參數是新打開的窗口的名字。若是指定的是一個以及存在的窗口的名字(而且腳本容許跳轉到那個窗口),會直接使用已經存在的窗口。不然,會打開新的窗口,並將這個指定的名字賦值給它。若是省略此參數,會使用指定的名字「_blank」打開新的、未命名的窗口。

須要注意的是,腳本是沒法經過簡單的猜想窗口的名字來控制操縱這個窗口中的web應用的,只有設置了「容許導航」(allowed to navigte)(html5規範術語)的頁面才能夠這樣。寬泛的講,當且僅當窗口包含的文檔來自相同的源或者是這個腳本打開了那個窗口(或者是遞歸地打開了窗口中打開的窗口),腳本才能夠經過名字來指定存在的窗口。還有,若是其中一個窗口是內嵌在另外一個窗口的裏的窗體,那麼它們的腳本直接就能夠相互導航。在這種狀況下,可使用保留的名字「_top」(頂級祖先窗口)和「_parent」(直接父級窗口)來獲取彼此瀏覽上下文。

open()的第三個可選參數是一個以逗號分隔的列表,包含大小和各類屬性,用以代表新窗口是如何打開的。若是省略它,新窗口會用一個默認的大小,並且帶有一整組標準的UI組件,即菜單欄/狀態欄、工具欄等。在標籤式瀏覽器中,會建立一個新的標籤。

另一方面,若是指定這個參數,就能夠指定窗口的尺寸,以及它包含的一組屬性。(顯式指定窗口支持更像是建立新窗口,而不是新標籤)例如,容許打開改變大小的瀏覽器窗口,而且包含狀態欄、工具欄,地址欄能夠這樣寫:

var w =window.open("smaillwin.html","smallwin","width=400,heigth=500,status=yes,resizeable=yes");

第三個參數是非標準的,html5規範也主張瀏覽器應該忽略它。參見第四部分中的window.open()查看在此參數中能夠指定什麼內容。注意,當指定第三個參數時,全部沒有顯式指定的功能都會忽略。出於各類安全緣由,瀏覽器包含對可能指定的功能的限制。例如:一般不容許指定一個過小或者位於屏幕以外才窗口,而且瀏覽器不容許建立一個沒有狀態欄的窗口。

open()的第四個參數只在第二個參數命名的是一個存在的窗口時纔有用。它是一個布爾值,聲明瞭由第一個參數是url是應用替換掉窗口瀏覽歷史的當前條目(true),仍是應該在窗口瀏覽歷史中建立一個新的條目false,後者爲默認設置。

open()的返回值是表明命名或新建立的窗口的window對象。能夠在本身的javascript代碼中使用這個window對象來引用新建立的窗口,就像使用隱式的window對象window來引用運行代碼的窗口同樣。

var w = window.open();
w.alert("to example.com");
w.location = "http://www.example.com"

在由window.open()方法建立的窗口中,opener屬性引用的是打開它的腳本的window對象。在其它窗口中,opener爲null:

w.opner !== true; //true, 對於任何由w建立的任意窗口
w.open().opener === w; //true,對於任意窗口w

window.open()是廣告商用來在你瀏覽網頁時採用的「頁面以前彈出」或「頁面以後彈出」窗口的一種方法。因爲這種方法的濫用,大部分瀏覽器增長了彈出窗口過濾系統,一般,open()方法只有當用戶單擊按鈕或者連接的時候纔會調用,javascript代碼嘗試在瀏覽器載入或關閉時開啓彈出一個窗口時,一般會失敗。將上面的代碼粘貼到瀏覽器javascript控制檯進行測試 ,可能會由於一樣的緣由而失敗。

關閉窗口

就像方法open()打開一個新窗口同樣,方法close()將關閉一個窗口。若是已經建立了window對象w,可使用以下的代碼將它關閉。

w.close()

運行在那個窗口中的javascript代碼則可使用下面的代碼關閉。以下

window.close();

注意,要顯式地使用標識符window。這樣能夠避免混淆window對象的close()方法和Document對象的close()方法,若是正在從事件處理程序調用close()。這很重要

大多瀏覽器只容許自動關閉由本身的javascript代碼建立的窗口。若是要關閉其餘窗口,能夠用一個對話框提示用戶,要求他對關閉窗口的請求進行確認或取消。在表示窗體而不是頂級窗口或標籤頁上的window對象執行close()方法不會有任何效果,它不能關閉一個窗體(反之能夠從它包含的文檔中刪除iframe)。

即便一個窗口關閉了,表明它的window對象仍然存在。已關閉的窗口會有個值爲爲true的closed屬性。它的Document會是null。它的方法一般不再會工做。

8.2.窗體之間的關係

咱們已經知道,window對象的方法open()返回表明新建立的窗口的window對象,並且這個新窗口具備opener屬性,該屬性能夠打開它的原始窗口。這樣,兩個窗口就能夠相互引用,彼此均可以讀取對方的屬性或是調用對方的方法。窗體也是這樣的,窗口或窗體中運行的代碼均可以經過下面介紹的屬性引用到本身的窗口或窗體,以及嵌套的子窗體。

任何窗口或窗體中的javascript代碼均可以將本身的窗口和窗體引用爲window或self.窗體能夠用parent屬性引用包含它的窗口或窗體的window對象。

parent.history.back();

若是一個窗口是頂層窗口或標籤,而不是窗體,那麼其parent屬性引用的就是這個窗口自己。

parent == self; //只有頂級窗口才會返回true

若是一個窗體包含在另外一個窗體中,然後者又包含在頂級窗口中,那麼該窗體就可使用parent.parent來引用頂級窗口。top屬性是一個通用的快捷方式,不管一個窗體被嵌套了幾層,它的top屬性引用的都是指向包含它的頂級窗口。若是一個window對象表明的是一個頂級窗口,那麼它的top屬性引用的就是窗口自己。對於那些頂級窗口的直接子窗口,top屬性就等價於parent屬性。

parent和top屬性容許腳本引用它的窗體的祖先。有不止一種方法能夠引用窗口或窗體的子孫窗體。窗體是經過iframe元素建立的。能夠用 獲取其餘元素的一個方法獲取一個表示iframe元素的對象。假定文檔裏有<iframe id="f1">,那麼表示該iframe元素的對象就是:

var iframeElement = document.getElementById("f1");

<iframe>元素有contentWindow屬性,引用該窗體的window對象,因此此窗體的window對象就是:

 var childFrame = document.getElementById("f1").contentWindow;

能夠進行反向操做——從表示窗體的window對象來獲取該窗體的<iframe>元素,用window對象的frameElement屬性。表示頂級窗口的window對象的frameElement屬性爲null。窗體中的window對象的frameElement屬性不是null:

var elt = document.getElementById("f1");
var win = elt.contentWindow;
win.frameElement === elt; //對於幀來講,永遠是true
window.frameElement === null; //對於頂級窗口來講,永遠是true

。。。。。。

8.3.交互窗口中的javascript

每一個窗口和窗體都是它自身的javascript執行上下文,以window做爲全局對象。可是若是一個窗口或窗體中的代碼能夠應用到其餘窗口或窗體(而且同源策略沒有阻止它),那麼一個窗口或窗體中的腳本就能夠和其它窗口或窗體的腳本進行交互。

設想一個web頁面中有兩個<iframe>元素 ,分別叫A和B,而且這些窗體所包含的文檔來自同一服務器,而且包含交互腳本,窗體A裏的腳本定義了一個變量i :

var i = 3;

這個變量只是全局對象的一個屬性,也是window對象的一個屬性。窗體A中的代碼能夠用標識符i來引用變量,或者用window對象顯式的引用這個變量:

window.i

因爲窗體B中的腳本能夠引用窗體A的window對象,所以它能夠引用那個window對象的屬性:

parent.A.i=4;//改變窗體A中的變量i的值

。。。。。。

相關文章
相關標籤/搜索