DIV CSS 佈局教程網

 DIV+CSS佈局教程網 >> 網頁腳本 >> JavaScript入門知識 >> 關於JavaScript >> 關於Document.defaultView
關於Document.defaultView
編輯:關於JavaScript     


引子

最近在寫一個可以將頁面上的資源鏈接轉為二維碼以方便移動端浏覽的chrome插件,由於dom操作並不多,而且作為插件不需要考慮跨
浏覽器兼容性,所以並沒有引入jQuery,而是使用原生的DOM API。其中有一個需求是判斷元素在頁面上的相對文檔的偏移offset。我使用
的方法如下:

function getOffset(ele){
if (!ele || ele.nodeType != 1) {
return;
}
var rect = ele.getBoundingClientRect(),
doc = ele.ownerDocument.documentElement;

return {
top: rect.top + window.pageYOffset - doc.clientTop,
left: rect.left + window.pageXOffset - doc.clientLeft
};

}
因為以前看過一點jQuery的源碼,又不需要注意兼容,所以寫起來還是比較順手的。這個方法,寫出來還算是挺好用的,沒發現什麼問題,
得意之時,想著,要不去看下jQuery是怎麼寫的,翻了下,源碼如下(version 2.1.1)

offset: function(options) {
if (arguments.length) {
return options === undefined ?
this :
this.each(function(i) {
jQuery.offset.setOffset(this, options, i);
});
}

var docElem, win,
elem = this[0],
box = {
top: 0,
left: 0
},
doc = elem && elem.ownerDocument;

if (!doc) {
return;
}

docElem = doc.documentElement;

// Make sure it's not a disconnected DOM node
if (!jQuery.contains(docElem, elem)) {
return box;
}

// If we don't have gBCR, just use 0,0 rather than error
// BlackBerry 5, iOS 3 (original iPhone)
if (typeof elem.getBoundingClientRect !== strundefined) {
box = elem.getBoundingClientRect();
}
win = getWindow(doc);
return {
top: box.top + win.pageYOffset - docElem.clientTop,
left: box.left + win.pageXOffset - docElem.clientLeft
};
}
看了下,除了一些兼容性處理,和一些對jQuery對象的操作外,基本和我的做法是一樣的,哈哈哈!突然瞄到了這麼個東西win = getWindow(doc),
趕緊看下源碼

function getWindow(elem) {
return jQuery.isWindow(elem) ? elem : elem.nodeType === 9 && elem.defaultView;
}
ちょっと待って,defaultView是什麼東西呢,我們知道nodeType為9時,該元素就是document,由於之前沒有使用過,
document.defaultView的結果和我代碼裡的window對象有什麼不同呢?

控制台查看

document.defaultView === window
//true
靠,這有什麼意義呢,是jQuery的裝B寫法麼?

查看DOM API文檔

打開MDN,我找到了關於defaultView的描述
,稍翻一下

Document.defaultView

概要:

在浏覽器中返回關聯document的window對象,如果沒有則返回null
用法:

var win = document.defaultView;

這是一個只讀屬性。

注意:

在quirksmode模式下, IE 9 以下版本不支持defaultView.
測試

好了,既然有這麼個API自然是有他的用途的,MDN的文檔表示defaultView是document關聯的window對象,那麼其用途肯定體現在當前上下文的window
不等於當前document關聯的window時,即window !== document.defaultView,那麼什麼上下文(context)會出現這種情況呢,我想到了三種:
1.frame;2.popup;3.extension

開測:
1.frame
index.html

<html>
<head>
</head>
<body>
<iframe src="frame.html" id="myframe" name="myframe">
</iframe>
<script>
</script>
</body>
</html>
frame.html

<html>
<head>
</head>
<body>
<p>I'm iFrame</p>
<script>
console.log(window === document.defaultView);
</script>
</body>
</html>
測試結果:true

2.pupup

var open = window.open('frame.html');
測試結果:true

3.extension

在我寫的這個chromePlugin裡我分別在background.js和content.js裡測試
無一例外window === document.defaultView都返回true。

這時我想到了firefox的擴展,但自己沒有開發FF擴展的經驗,就去google了一下,發現了這個,
大致意思是說,“如果你的擴展運行在FireFox 31以下的版本,在content.js裡必須使用document.defaultView.postMessage”。

看到這裡,我忽然想起jQuery源碼中的defaultView也許就是為了兼容某些Firefox版本,哈哈,繼續Google

終於,讓我在MDN上找到了這個傳送門

In many code samples online, getComputedStyle is used from the document.defaultView object. In nearly all cases, this is needless, as getComputedStyle exists on the window object as well. It's likely the defaultView pattern was some combination of (1) folks not wanting to write a spec for window and (2) making an API that was also usable in Java. However, there is a single case where the defaultView's method must be used: when using Firefox 3.6 to access framed styles.
很顯然,坑就在這裡了,當使用Firefox 3.6時,其frame中需要使用document.defaultView去獲取window對象,才能使用其getComputedStyle方法。
好了,這個問題告一段落。

後記
不止一次聽人抱怨jQuery的代碼是多麼的糟(qiang)糕(da),其運用大量的黑魔法,各種奇技淫巧去兼容所有的浏覽器,即使已到2.1.1版本,仍然保持著對FF低版本的支持。
想想看在那個前端開發,還處在蠻荒的時代,jQuery的出現,還真是裡程碑意義的事件,他極大力度的解放了前端的生產力,讓前端開發人員,
有時間和精力去開發各種前端工具,規范,才有了大前端時代的來臨。哈哈,吹的有點多,干貨略少。
XML學習教程| jQuery入門知識| AJAX入門| Dreamweaver教程| Fireworks入門知識| SEO技巧| SEO優化集錦|
Copyright © DIV+CSS佈局教程網 All Rights Reserved