JavaScript: Class.method vs. Class.prototype.method
499
¿Cuál es la diferencia entre las siguientes dos declaraciones?
Class.method =function(){/* code */}Class.prototype.method =function(){/* code using this.values */}
¿Está bien pensar en la primera declaración como una declaración de un método estático, y la segunda declaración como una declaración de un método de instancia?
Sí, la primera función no tiene relación con una instancia de objeto de esa función constructora , puede considerarla como un 'método estático' .
En JavaScript, las funciones son objetos de primera clase , lo que significa que puede tratarlos como cualquier objeto, en este caso, solo está agregando una propiedad al objeto de función .
La segunda función, a medida que amplíe el prototipo de la función de constructor, estará disponible para todas las instancias de objeto creadas con la newpalabra clave, y el contexto dentro de esa función (la thispalabra clave) se referirá a la instancia de objeto real donde la llame.
Considere este ejemplo:
// constructor functionfunctionMyClass(){var privateVariable;// private member only available within the constructor fnthis.privilegedMethod =function(){// it can access private members//..};}// A 'static method', it's just like a normal function // it has no relation with any 'MyClass' object instanceMyClass.staticMethod =function(){};MyClass.prototype.publicMethod =function(){// the 'this' keyword refers to the object instance// you can access only 'privileged' and 'public' members};var myObj =newMyClass();// new object instance
myObj.publicMethod();MyClass.staticMethod();
Cuando crea más de una instancia de MyClass, solo tendrá una sola instancia de publicMethod en la memoria, pero en caso de privilegedMethod terminará creando muchas instancias y staticMethod no tiene relación con una instancia de objeto.
Es por eso que los prototipos ahorran memoria.
Además, si cambia las propiedades del objeto padre, si la propiedad correspondiente del niño no se ha cambiado, se actualizará.
Para estudiantes visuales, al definir la función sin .prototype
ExampleClass=function(){};ExampleClass.method =function(customString){
console.log((customString !==undefined)?
customString :"called from func def.");}ExampleClass.method();// >> output: `called from func def.` var someInstance =newExampleClass();
someInstance.method('Called from instance');// >> error! `someInstance.method is not a function`
Con el mismo código, si .prototypese agrega,
ExampleClass.prototype.method =function(customString){
console.log((customString !==undefined)?
customString :"called from func def.");}ExampleClass.method();// > error! `ExampleClass.method is not a function.` var someInstance =newExampleClass();
someInstance.method('Called from instance');// > output: `Called from instance`
Para hacerlo más claro,
ExampleClass=function(){};ExampleClass.directM =function(){}//M for methodExampleClass.prototype.protoM =function(){}var instanceOfExample =newExampleClass();ExampleClass.directM();✓ works
instanceOfExample.directM(); x Error!ExampleClass.protoM(); x Error!
instanceOfExample.protoM();✓ works
**** Nota para el ejemplo anterior, someInstance.method () no se ejecutará, ya que
ExampleClass.method () causa un error y la ejecución no puede continuar.
Pero en aras de la ilustración y la fácil comprensión, he mantenido esta secuencia. ****
Resultados generados desde chrome developer console&
Haga clic en el enlace jsbin de arriba para recorrer el código.
Alternar la sección comentada con +JS Bin
Mire cómo staticse utilizó la palabra clave para declarar el método estático isPerson.
Para crear un objeto de Personclase.
const aminu = new Person("Aminu", "Abubakar");
Usando el método estático isPerson.
Person.isPerson(aminu); // will return true
Usando el método de instancia sayHi.
aminu.sayHi(); // will return "Hi Aminu"
NOTA: Ambos ejemplos son esencialmente los mismos, JavaScript sigue siendo un lenguaje sin clases. El classintroducido en ES6 es principalmente un azúcar sintáctico sobre el modelo de herencia basado en prototipos existente.
"En ES6" usted describe una sintaxis de azúcar solamente. Esta no es la forma de hacerlo "ES2015" (por favor, todos dejen de usar ES6, use el término apropiado ES2015). Es simplemente otra forma de hacerlo y, en mi opinión, la forma incorrecta.
K - La toxicidad en SO está creciendo.
2
@KarlMorrison Aminu no escribió "forma de hacerlo", simplemente lo escribió usted mismo y tomó la excepción. Su punto puede ser justo sobre ES6 vs ES2015, pero en la conversación las personas a menudo recurren a una convención más corta para la eficiencia, por lo que creo que eliminarlo de la escritura no es posible o seguro.
wuliwong
Gracias por la parte ES6 de su respuesta; eso aclara mucho, especialmente cuando se combina con las 2 respuestas "públicas + privilegiadas" anteriores. Sin embargo estoy totalmente confundido por su obj.constructor === Personbienestar trueejemplo, aunque ... Whaaaat? ¿Cómo puede el constructor de una instancia de ===clase la clase misma ...? (Eso es como decir que un subconjunto de un conjunto es el conjunto en sí, etc.)
Andrew
Ohhh ... ¿esto es todo para decir que, literalmente, el constructor es todo lo que una clase JS realmente es al final del día? ¿Todo lo demás está amontonado en el constructor o es una construcción totalmente estática aislada de la clase, excepto por nombre / concepto (y como un "esto" implícito que está disponible obviamente)? (Por lo tanto, lo que pensé que era un subconjunto del conjunto no era en realidad un subconjunto)
Cuando crea más de una instancia de MyClass, solo tendrá una sola instancia de publicMethod en la memoria, pero en caso de privilegedMethod terminará creando muchas instancias y staticMethod no tiene relación con una instancia de objeto.
Es por eso que los prototipos ahorran memoria.
Además, si cambia las propiedades del objeto padre, si la propiedad correspondiente del niño no se ha cambiado, se actualizará.
fuente
Para estudiantes visuales, al definir la función sin
.prototype
Con el mismo código, si
.prototype
se agrega,Para hacerlo más claro,
**** Nota para el ejemplo anterior, someInstance.method () no se ejecutará, ya que
ExampleClass.method () causa un error y la ejecución no puede continuar.
Pero en aras de la ilustración y la fácil comprensión, he mantenido esta secuencia. ****
Resultados generados desde
chrome developer console
& Haga clic en el enlace jsbin de arriba para recorrer el código. Alternar la sección comentada con +JS Bin
ctrl/
fuente
Sí, el primero
static method
también se llamaclass method
, mientras que el segundo es uninstance method
.Considere los siguientes ejemplos para comprenderlo con más detalle.
En ES5
En el código anterior,
isPerson
es un método estático, mientras quesayHi
es un método de instancia dePerson
.A continuación, se muestra cómo crear un objeto desde el
Person
constructor.var aminu = new Person("Aminu", "Abubakar");
Usando el método estático
isPerson
.Person.isPerson(aminu); // will return true
Usando el método de instancia
sayHi
.aminu.sayHi(); // will return "Hi Aminu"
En ES6
Mire cómo
static
se utilizó la palabra clave para declarar el método estáticoisPerson
.Para crear un objeto de
Person
clase.const aminu = new Person("Aminu", "Abubakar");
Usando el método estático
isPerson
.Person.isPerson(aminu); // will return true
Usando el método de instancia
sayHi
.aminu.sayHi(); // will return "Hi Aminu"
NOTA: Ambos ejemplos son esencialmente los mismos, JavaScript sigue siendo un lenguaje sin clases. El
class
introducido en ES6 es principalmente un azúcar sintáctico sobre el modelo de herencia basado en prototipos existente.fuente
obj.constructor === Person
bienestartrue
ejemplo, aunque ... Whaaaat? ¿Cómo puede el constructor de una instancia de===
clase la clase misma ...? (Eso es como decir que un subconjunto de un conjunto es el conjunto en sí, etc.)