2012-11-07 31 views
0

如果有人想爲舊瀏覽器實現一個功能(例如Array.prototype.filter)哪種方法更好?爲什麼?每個人的利弊是什麼?擴展類或創建新函數哪個更好?

if (!Array.prototype.filter) { 
    Array.prototype.filter = function() { 
    //implementation 
    } 
} 

function myFilter(e,i,f) { 
    if (!Array.prototype.filter) { 
     //implementation 
    } else { 
     return Array.prototype.filter(e,i,f); 
    } 
} 

回答

1

第二種方法是更常見;它被jQuery和Underscore.js等流行的shim JS庫所使用。

說,延長本地對象是遠低於危險再延長主機對象(與後者,這是典型的「第二十二條軍規」:你延長他們在不處理的延伸瀏覽器提供額外的功能主機對象足夠好)。 This article總結:

不要忘記寫適當的,順從的墊片很難。在懷疑 時,使用獨立對象。當您正在填充的方法是未完成規範的部分 時,請使用獨立對象。只有當您遵守方法並且方法是完成的 面向未來的規範的一部分時,直接填充本地對象纔是安全的。

+0

這也正是我的問題,爲什麼jQuery和下劃線認爲第二種方法是更好選擇的樣機第一種方法 你的意思是什麼「......這手柄延伸本地對象沒有這麼好。」 – PHPst

+1

我不同意(至少直到提供了更老的瀏覽器問題的更詳細的解釋,並且如果它讓我信服)。只要墊片表現爲標準方法,我認爲沒有任何問題可以使本地物體變淺。相關閱讀:http://perfectionkills.com/extending-built-in-native-objects-evil-or-not/ – bfavaretto

+0

@bfavaretto當然,你是對的。我寫了這個回答,認爲這個問題是關於主機對象的(同樣),而與本地對象不同。儘管如此,我更喜歡使用「獨立」對象方法,因此「不要修改你不擁有的對象」最大值。它迄今爲止付出了代價。 – raina77ow

2

就我個人而言,我大多數時候使用第一種方法(加入Array.prototype.filter),但有些時候我不會。在爲舊瀏覽器編寫大型框架時,我不會使用第一種方法,這些框架需要與互聯網上的任何其他腳本(包括壞的腳本)搭配使用。

以下是需要考慮的事項。比方說,你在使用Array.prototype.filter您所描述的方法勻,然後添加一個第三方腳本到你的網站,做這樣的事情:

var someArray = [ 'a', 'b', 'c' ]; 
console.log('The first three letters of the alphabet are: '); 
for (var i in someArray) 
    console.log(someArray[i]); 

結果?

The first three letters of the alphabet are: 
a 
b 
c 
function() { ... } 

您的過濾器功能被打印出來了!現在,在技術層面上,沒有人應該使用for...in循環迭代數組,但無法控制第三方腳本可能執行的操作。這是主要的缺點,當你編寫一個大型的圖書館在整個互聯網上使用時,這是值得考慮的。

這樣可以防止添加任何東西Object.prototype,時間(用一個簡單的Object.prototype.method =函數(){...} assignment), because爲...在is good to use on other types of objects, and this kind of shimming breaks爲... in`。

但是,如果你只是寫代碼在自己的網站上使用,並且你知道你將包括的腳本是高質量的並且不會犯這樣的錯誤,這是一種很好的技術。

此外,如果您的代碼僅用於兼容ECMAScript 5的瀏覽器,則可以將您的墊片定義爲不可枚舉的,這將防止它們在for...in循環中出現。我目前工作的一個項目在ECMAScript中勻場6層的方法ES5的瀏覽器,而且由於它的唯一目的是在ES5瀏覽器中運行,我可以逃脫:

Object.defineProperty(Array.prototype, 'contains', { 
    value: function(value) { 
     // Implementation 
    }, 
    enumerable: false, 
    writable: true, 
    configurable: true 
}); 

定義墊片以這種方式阻止其顯示了在for...in循環,所以它甚至安全上Object.prototype使用,提供您的實現精確地跟隨規範/草案

它會彈出一個輔助點。如果你沒有信心,你可以按照規範準確地實現這個方法,但是最好不要將它放入其中。這可能會破壞檢查內置的庫並在可用的情況下使用它,但是會回退到某種程度否則,如果不是。更好地讓他們沒有任何東西,而不是一個破碎的實施。

這是出於這個原因,我從來沒有嘗試實現部分墊片。例如,Object.create不能在ES3瀏覽器中完全實現,所以我不會永遠填充這個。我只是使用我自己的myLibrary.create函數,它的功能可能類似,但至少任何可能檢查是否存在Object.create的代碼都不會誤認爲它具有完整的工作版本。

這個故事告訴我們:如果你要勻,檢查出一些對MDN真正真棒,符合規範的墊片,並學會寫代碼喜歡它:Array.prototype.filter


最後注意:許多圖書館在Array.prototype的方法中沒有采取措施的原因可能部分是由於這些考慮因素中的一部分,但在許多情況下也存在歷史原因。像jQuery這樣的庫正在開發之前filter是一種標準的內置方法。 Prototype.js採取了的方法,加入了非標準方法,這比上面討論的方法有更多的缺點。 jQuery決定不向內置原型添加非標準方法,這就是爲什麼他們有$.filter

0

對於新標準的js函數和類最好的做法是,擴展類,如果在舊版瀏覽器中找不到的功能。

但如果功能不成爲標準的最佳實踐創造了新的功能,不改變標準類,因爲如果你使用的是可能在將來與不同的行爲中使用的函數名它會破壞你的應用程序。

相關問題