2012-02-19 29 views
52

我需要在JS中編寫一些擴展方法。我知道如何在C#中做到這一點。例如:如何在JavaScript中編寫擴展方法?

string firstName = "Bob"; 
string hi = firstName.SayHi(); 

我會怎麼做在JavaScript這樣的事情:

public static string SayHi(this Object name) 
{ 
    return "Hi " + name + "!"; 
} 

,然後叫什麼名字?

回答

94

在這種特定的情況下,你的方法分配給String.prototype,像這樣:

String.prototype.SayHi = function SayHi() { 
    return "Hi " + this + "!"; 
}; 

或使用Object.defineProperty(ES5高,所以基本上,一切,但IE8和不可枚舉的屬性更好更早):

Object.defineProperty(String.prototype, "SayHi", { 
    value: function SayHi() { 
     return "Hi " + this + "!"; 
    } 
}); 

JavaScript是一種原型語言。這意味着每個對象都支持原型對象。在JavaScript中,該原型由對象的構造函數分配,或由新的(ish)ECMAScript5 Object.create函數分配。

在前一種情況下(構造函數),分配給對象的原型由構造函數的prototype屬性定義。所以,如果你有一個構造函數調用Foo

function Foo() { 
} 

...那麼語句

var f = new Foo(); 

...分配Foo.prototypef實例作爲其原型對象。因此:

function Foo(b) { 
    this.baz = b; 
} 
Foo.prototype.bar = function bar() { 
    console.log(this.baz); 
}; 

var f = new Foo("Charlie"); 
f.bar(); // logs "Charlie" 
在你的榜樣

那麼,既然firstNameString實例(實際上是一個原始的字符串,不過不用擔心,它就會自動地晉升爲String實例在必要時),它的原型是String.prototype,所以將屬性添加到String.prototype,該屬性引用您的SayHi函數可使該函數在所有String實例上可用。

由於DougR在評論中指出,從C#擴展方法的一個區別是,C#的擴展方法can be called on null references(如果你有一個string擴展方法,string s = null; s.YourExtensionMethod();實際工作)。這不適用於JavaScript; null是它自己的類型,沒有原型可以擴展它。


有關這些示例中的函數名稱的簡要說明,例如,

Object.defineProperty(String.prototype, "SayHi", { 
    value: function SayHi() { 
// HERE ------------^ 
     return "Hi " + this + "!"; 
    } 
}); 

Foo.prototype.bar = function bar() { 
// AND HERE -----------------^ 
    console.log(this.baz); 
}; 

該表單中,我們使用一個函數表達式與它的名稱(「命名的函數表達式」,又名NFE)那裏曾經是著名的有關於IE8的問題(或更早;以及在其他幾個瀏覽器的真正老版本上)。隨着一切都死了,IE8是死了,有沒有必要擔心NFEs了。(即使在IE8中,上面也沒關係。)

+0

@DougR:對不起,標準註釋清理。當評論變得過時時,mod或高級用戶可以將其刪除(mod可以直接執行,高級用戶必須在審查隊列中合作)。我已經更新了答案,表明你已經標記了這一點。 :-) – 2015-01-11 10:24:14

+1

@Grundy:謝謝,是的,'String s = null'的全部點''部分是使用's.YourExtensionMethod()'!欣賞這一點。 :-) – 2015-01-11 11:07:02

+0

感謝您高亮顯示擴展方法對空實體有效。 – Rama 2016-04-19 07:40:16