JavaScript: Class.method vs. Class.prototype.method
499
Qual é a diferença entre as duas declarações a seguir?
Class.method =function(){/* code */}Class.prototype.method =function(){/* code using this.values */}
Tudo bem pensar na primeira declaração como uma declaração de um método estático e na segunda declaração como uma declaração de um método de instância?
Sim, a primeira função não tem relação com uma instância de objeto dessa função construtora , você pode considerá-la como um 'método estático' .
No JavaScript, as funções são objetos de primeira classe , o que significa que você pode tratá-las como qualquer objeto; nesse caso, você está apenas adicionando uma propriedade ao objeto de função .
A segunda função, à medida que você estende o protótipo da função construtora, estará disponível para todas as instâncias de objeto criadas com a newpalavra - chave e o contexto nessa função (a thispalavra - chave) se referirá à instância real do objeto em que você a chama.
Considere este exemplo:
// 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();
Mas por que Function.prototype.method == Function.method?
Raghavendra
1
@Raghavendra não é
Zorgatone
1
@Menda Seu link está morto #
Eugen Sunic
19
Ao criar mais de uma instância do MyClass, você ainda terá apenas uma instância do publicMethod na memória, mas no caso do privilegedMethod, você acabará criando muitas instâncias e o staticMethod não terá relação com uma instância do objeto.
É por isso que os protótipos economizam memória.
Além disso, se você alterar as propriedades do objeto pai, se a propriedade correspondente da criança não tiver sido alterada, ela será atualizada.
Para aprendizes visuais, ao definir a função sem .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`
Com o mesmo código, se .prototypefor adicionado,
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 tornar mais 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
**** Observe o exemplo acima, someInstance.method () não será executado, pois
ExampleClass.method () causa erro e a execução não pode continuar.
Mas, para fins ilustrativos e de fácil compreensão, mantive essa sequência. ****
Resultados gerados a partir de chrome developer console&
Clique no link jsbin acima para percorrer o código.
Alternar seção comentada com +JS Bin
Veja como a staticpalavra-chave foi usada para declarar o método estático isPerson.
Para criar um objeto de Personclasse.
const aminu = new Person("Aminu", "Abubakar");
Usando o método estático isPerson.
Person.isPerson(aminu); // will return true
Usando o método de instância sayHi.
aminu.sayHi(); // will return "Hi Aminu"
NOTA: Ambos os exemplos são essencialmente os mesmos, o JavaScript permanece uma linguagem sem classe. O classintroduzido no ES6 é principalmente um açúcar sintático sobre o modelo de herança baseado em protótipo existente.
"No ES6", você descreve apenas um açúcar de sintaxe. Esta não é a maneira "ES2015" (todos parem de usar o ES6 e use o termo adequado ES2015). É simplesmente outra maneira de fazê-lo e, na minha opinião, o caminho incorreto.
K - A toxicidade no SO está crescendo.
2
@KarlMorrison Aminu não escreveu "maneira de fazê-lo", você acabou de escrever isso e fez uma exceção. Seu ponto de vista pode ser justo sobre o ES6 vs o ES2015, mas nas conversas as pessoas geralmente recorrem a uma convenção mais curta de eficiência, então acho que removê-la da escrita não é possível ou com certeza é aconselhável.
Wuliwong
Obrigado pela parte ES6 da sua resposta; isso esclarece muito, especialmente quando combinado com as 2 respostas "públicas + privilegiadas" acima. No entanto, estou completamente confuso por você obj.constructor === Personser trueexemplo ... O que? Como pode o construtor de uma instância de ===classe a própria classe ...? (Isso é como dizer que um subconjunto de um conjunto é o próprio conjunto, etc ...)
Andrew
Ohhh ... isso é tudo o que dizer então que, literalmente, o construtor é tudo o que realmente é uma classe JS no final do dia? Todo o resto é empilhado no construtor ou totalmente construtivo estático isolado da classe, exceto pelo nome / conceito (e como um "isto" implícito sendo disponibilizado obviamente)? (Portanto, o que eu pensei que era um subconjunto do conjunto não era realmente um subconjunto.)
Ao criar mais de uma instância do MyClass, você ainda terá apenas uma instância do publicMethod na memória, mas no caso do privilegedMethod, você acabará criando muitas instâncias e o staticMethod não terá relação com uma instância do objeto.
É por isso que os protótipos economizam memória.
Além disso, se você alterar as propriedades do objeto pai, se a propriedade correspondente da criança não tiver sido alterada, ela será atualizada.
fonte
Para aprendizes visuais, ao definir a função sem
.prototype
Com o mesmo código, se
.prototype
for adicionado,Para tornar mais claro,
**** Observe o exemplo acima, someInstance.method () não será executado, pois
ExampleClass.method () causa erro e a execução não pode continuar.
Mas, para fins ilustrativos e de fácil compreensão, mantive essa sequência. ****
Resultados gerados a partir de
chrome developer console
& Clique no link jsbin acima para percorrer o código. Alternar seção comentada com +JS Bin
ctrl/
fonte
Sim, o primeiro
static method
também é chamadoclass method
, enquanto o segundo é uminstance method
.Considere os seguintes exemplos, para entendê-lo com mais detalhes.
No ES5
No código acima,
isPerson
é um método estático, enquantosayHi
é um método de instância dePerson
.Abaixo, é como criar um objeto a partir do
Person
construtor.var aminu = new Person("Aminu", "Abubakar");
Usando o método estático
isPerson
.Person.isPerson(aminu); // will return true
Usando o método de instância
sayHi
.aminu.sayHi(); // will return "Hi Aminu"
No ES6
Veja como a
static
palavra-chave foi usada para declarar o método estáticoisPerson
.Para criar um objeto de
Person
classe.const aminu = new Person("Aminu", "Abubakar");
Usando o método estático
isPerson
.Person.isPerson(aminu); // will return true
Usando o método de instância
sayHi
.aminu.sayHi(); // will return "Hi Aminu"
NOTA: Ambos os exemplos são essencialmente os mesmos, o JavaScript permanece uma linguagem sem classe. O
class
introduzido no ES6 é principalmente um açúcar sintático sobre o modelo de herança baseado em protótipo existente.fonte
obj.constructor === Person
sertrue
exemplo ... O que? Como pode o construtor de uma instância de===
classe a própria classe ...? (Isso é como dizer que um subconjunto de um conjunto é o próprio conjunto, etc ...)