2012-08-02 39 views
5

可能重複:
In Javascript, can you extend the DOM?如何擴展DOM元素作爲類(無jQuery的)

我想補充的方法和屬性的元素。它沒有被列爲全球課程。我可以這樣擴展字符串:

String.prototype.dosomething = function { ... }; 

我嘗試這樣的(這是更大的,這是基本的):

function $id(str){ 
    this.element = document.getElementById(str); 
    return element; 
} 
var myElem = $id('myId'); // WORKS !!! 
$id.prototype.dosomethig = function (... }; 
var myValue = $id('myId').dosomething(); // DOESN'T WORK !!! 

我嘗試用其他方式,但問題是始終不變的,當我儘量延長班級,這是行不通的。有沒有辦法避免這種情況?我知道jQuery做到了這一點,但我想做我的專利 - 如果可以的話,我可以......對吧?

編輯: 下面在Safari和Firefox已經工作的代碼...

Element.prototype.pos = function(){ 
    var curleft = this.offsetLeft; 
    var curtop = this.offsetTop; 
    var scrleft = this.scrollLeft; 
    var scrtop = this.scrollTop; 
    var pElement = pElementScr = this.offsetParent 
    while(pElement){ 
     curleft += pElement.offsetLeft; 
     curtop += pElement.offsetTop; 
     pElement = pElement.offsetParent; 
    } 
    while(pElementScr){ 
     scrleft += pElementScr.scrollLeft; 
     scrtop += pElementScr.scrollTop; 
     pElementScr = pElementScr.offsetParent; 
    } 
    return {x:this.offsetLeft, y:this.offsetTop}; 
} 

它給連內有很多其他的div的div的位置。在解決了我的庫的很多其他問題後,我會嘗試在IE8中進行測試。

+2

你應該閱讀http://perfectionkills.com/whats-wrong-with-extending-the-dom/ – 2012-08-02 20:49:34

+1

AFAIK,jQuery的沒有做到這一點。他們提供了一個包裝,但是避免碰到DOM原型。 – tucuxi 2012-08-02 20:51:10

回答

4

在Firefox,Chrome和IE8 +元素從Element.prototype繼承,所以你必須做到:

Element.prototype.doSomething = function() { 
    alert("hello"); 
}; 

擴展主機的原型是很脆弱的,不推薦,但應該是罰款,如果你只是玩弄。主要原因是DOM規範沒有指定原型實現,而只是接口,elem.appendChild()應該可以工作,它不一定在某些原型中。


此:

function $id(str) { 
    this.element = document.getElementById(str); 
    return element; 
} 

,只是因爲中不需要的行爲this指的是當一個函數時沒有任何對象上下文中調用(這應該只是平了在拋出一個錯誤的全局對象只看到this,雖然嚴格模式通過將其設置爲undefined來稍微修復此問題)。您正在創建一個全局變量element(因爲全局對象的屬性分配成爲全局變量),然後返回全局變量。

+0

你能否詳細說一下,爲什麼它很脆弱? – 2012-08-02 20:49:40

+0

@ srini.venigalla看到FelixKling對你的問題的評論 – Esailija 2012-08-02 20:51:06

+0

同意 - 這是非常脆弱的,應該避免 – tucuxi 2012-08-02 20:51:22

0
$id('myId').dosomething() 

$ id('myId')是一個元素。

您在'元素'中沒有一個名爲doS​​omething的函數,您在$ id上有一個函數。實際上,當你爲一個函數添加一個函數會發生什麼,有可能嗎?

+0

他沒有分配函數給函數,他把它分配給'$ id.prototype.dosomethig','$ id.prototype'是一個對象。但是,當然,因爲函數是對象,它們可以具有任意屬性。 – 2012-08-02 20:54:32

+0

@Felix right .. $ id返回一個元素,他爲它添加了一個函數,然後爲'myId'創建了一個實例,爲什麼它沒有得到擴展? – 2012-08-02 20:59:11

+0

他返回'element',因爲它沒有被定義,所以實際上應該拋出一個錯誤。他必須從'$ id'返回'this'。 – 2012-08-02 21:01:13

0

首先,擴展DOM常常是(閱讀:總是)不好的選擇。如果你想編寫快速,跨瀏覽器的代碼,你不應該擴展DOM或其​​他本地對象(Object,String ...)。擴展本地對象也可能導致庫的兼容性問題等。如果您想了解更多關於主題,我建議你看看這個優秀的博客文章:http://perfectionkills.com/whats-wrong-with-extending-the-dom/

如果支持舊版本的IE(IE6 & & 7)是不是對你很重要,那麼這是你想要的:

Element.prototype.doSomething = function() { 
    // Your code here 
}; 

在你的例子中,問題是,$ id返回一個元素。您的「doSomething」附加到函數$ id,而不是它返回的元素。

這樣做的工作:

function $id(str){ 
    this.element = document.getElementById(str); 
    return this; 
} 
+0

好。這解決了幾乎所有的IF如何在IE8中工作。我不打算與舊版本兼容。有趣的是,我的js中沒有一個引用列表Element作爲一個類。 – Gustavo 2012-08-02 23:06:54

1

而是擴展DOM對象,爲什麼不把它包起來,有點像jQuery不會。

var myLib = { 
    addWrapper: function (id) { 
     return new this.WrapperClass(document.getElementById(id)); 
    }, 
    WrapperClass: function (element) { 
     this.element = element; 
    } 
}; 
MyLib.WrapperClass.prototype.someMethod = function() { 
    alert(this.element); 
} 

var wrappedElement = myLib.addWrapper('someid'); 
wrappedElement.someMethod(); 
+0

我從來沒有這樣工作,我會嘗試。 – Gustavo 2012-08-02 23:11:22