2012-02-19 13 views
52

Necesito escribir algunos métodos de extensión en JS. Sé exactamente cómo hacer esto en C#. Ejemplo:¿Cómo escribo un método de extensión en JavaScript?

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

y luego llamó por:

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

¿Cómo voy a hacer algo como esto en JavaScript?

Respuesta

94

En ese caso específico, que le asigna su método para String.prototype, así:

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

o mejor como una propiedad para no numerable usando Object.defineProperty (ES5 y superior, así que básicamente, todo menos IE8 y anterior):

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

JavaScript es un lenguaje prototípico. Eso significa que cada objeto está respaldado por un objeto prototipo . En JavaScript, ese prototipo es asignado por la función de constructor para el objeto o por la nueva función (ish) ECMAScript5 Object.create.

En el primer caso (la función constructora), el prototipo asignado a un objeto se define mediante la propiedad prototype de la función constructora. Así que si usted ha llamado una función constructora Foo:

function Foo() { 
} 

... entonces la declaración

var f = new Foo(); 

... Foo.prototype asigna a la instancia f como su objeto prototipo. Por lo tanto:

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

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

Así que en su ejemplo, ya que es una firstNameString ejemplo (en realidad una cadena primitiva, pero no se preocupen, que se automagicamente promovido a una instancia de String siempre que sea necesario), su prototipo es String.prototype, por lo agregar una propiedad a String.prototype que hace referencia a su función SayHi hace que esa función esté disponible en todas las instancias de String.

Como DougR señalado en un comentario, una diferencia de C# los métodos de extensión es que los métodos de extensión de C# 's can be called on null references (si tiene un método string extensión, string s = null; s.YourExtensionMethod(); funciona en realidad). Esto no es verdad con JavaScript; null es de su propio tipo y no hay ningún prototipo para extenderlo.


Una nota rápida sobre los nombres de funciones en esos ejemplos, p.

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

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

Esa forma, en el que estamos utilizando una expresión función con un nombre en ella (una "expresión de la función denominada" alias ENF) solía ser famosa por tener problemas (en IE8 y anteriores; y en versiones muy, muy viejas de un par de otros navegadores). Con todo lo demás muerto y IE8 siendo casi muerto, ya no hay necesidad de preocuparse por las NFE.(Y lo anterior estaría bien incluso en IE8.)

+0

@DougR: Lo sentimos, limpieza de comentarios estándar. Cuando un comentario se vuelve obsoleto, los mods o los usuarios avanzados pueden eliminarlo (las modificaciones pueden hacerlo directamente, los usuarios avanzados deben formar equipo en la cola de revisión). He actualizado la respuesta para decir que has marcado esto. :-) –

+1

@Grundy: gracias, sí, el objetivo de la parte 'String s = null;' fue utilizar 's.YourExtensionMethod()'! Apreciar la captura. :-) –

+0

Gracias por destacar que el método de extensión funciona para entidades nulas. – Rama

Cuestiones relacionadas