2012-02-19 17 views
52

Ho bisogno di scrivere alcuni metodi di estensione in JS. So come farlo in C#. Esempio:Come scrivere un metodo di estensione in JavaScript?

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

e poi chiamato da:

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

Come dovrei fare qualcosa di simile in JavaScript?

risposta

94

In questo caso specifico, ci si assegna il metodo per String.prototype, in questo modo:

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

o meglio come una proprietà non enumerabile utilizzando Object.defineProperty (ES5 e più alto, in modo sostanzialmente, tutto, ma IE8 e precedente):

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

JavaScript è un linguaggio prototipo. Ciò significa che ogni oggetto è supportato da un oggetto prototipo . In JavaScript, questo prototipo viene assegnato dalla funzione di costruttore per l'oggetto o dalla nuova funzione (ish) ECMAScript5 Object.create.

Nel primo caso (la funzione di costruzione), il prototipo assegnato a un oggetto è definito dalla proprietà prototype della funzione di costruzione. Quindi, se avete una funzione di costruzione chiamato Foo:

function Foo() { 
} 

... allora l'istruzione

var f = new Foo(); 

... assegna Foo.prototype all'istanza f come oggetto prototipo. Così:

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

var f = new Foo("Charlie"); 
f.bar(); // logs "Charlie" 

Quindi nel tuo esempio, dal momento che firstName è un'istanza String (in realtà una stringa primitiva, ma non preoccupatevi, si ottiene automagicamente promosso a un'istanza String quando necessario), il suo prototipo è String.prototype, così l'aggiunta di una proprietà a String.prototype che fa riferimento alla funzione SayHi rende tale funzione disponibile su tutte le istanze String.

Come DougR sottolineato in un commento, una differenza da C# i metodi di estensione è che i metodi di estensione C# s 'can be called on null references (se si dispone di un metodo string estensione, string s = null; s.YourExtensionMethod(); funziona in realtà). Questo non è vero con JavaScript; null è un tipo proprio e non esiste un prototipo da estendere per questo.


Una breve nota sui nomi di funzione in questi esempi, ad es.

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

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

Quella forma, dove stiamo utilizzando una funzione di espressione con un nome in esso (una "funzione un'espressione nominata," aka NFE) usato per essere famosa per avere problemi (su IE8 e precedenti; e su versioni veramente vecchie di un paio di altri browser). Con tutto il resto essere morto e IE8 essendo quasi morto, non c'è più bisogno di preoccuparsi per gli NFE.(E quanto sopra sarebbe ok anche in IE8.)

+0

@DougR: Siamo spiacenti, pulizia dei commenti standard. Quando un commento diventa obsoleto, i mod o gli utenti esperti possono rimuoverlo (i mod possono farlo direttamente, gli utenti devono collaborare nella coda di revisione). Ho aggiornato la risposta per segnalare che l'hai segnalato. :-) –

+1

@Grundy: Grazie, sì, l'intero punto della stringa 'String s = null;' parte doveva usare 's.YourExtensionMethod()'! Apprezzo il pescato. :-) –

+0

Grazie per aver evidenziato che il metodo di estensione funziona per entità null. – Rama

Problemi correlati