Qual é a diferença entre
var A = function () {
this.x = function () {
//do something
};
};
e
var A = function () { };
A.prototype.x = function () {
//do something
};
a1.x !== a2.x
:; no protótipo:a1.x === a2.x
Qual é a diferença entre
var A = function () {
this.x = function () {
//do something
};
};
e
var A = function () { };
A.prototype.x = function () {
//do something
};
a1.x !== a2.x
:; no protótipo:a1.x === a2.x
Respostas:
Os exemplos têm resultados muito diferentes.
Antes de analisar as diferenças, deve-se observar o seguinte:
[[Prototype]]
propriedade privada da instância .myObj.method()
), isso dentro do método faz referência ao objeto. Quando isso não é definido pela chamada ou pelo uso de ligação , o padrão é o objeto global (janela em um navegador) ou no modo estrito, permanece indefinido.Então, aqui estão os trechos em questão:
var A = function () {
this.x = function () {
//do something
};
};
Nesse caso, A
é atribuído à variável um valor que é uma referência a uma função. Quando essa função é chamada usando A()
, a função é esta não é definida pela chamada para o padrão é o objeto global e a expressão this.x
é eficaz window.x
. O resultado é que é atribuída uma referência à expressão da função no lado direito window.x
.
No caso de:
var A = function () { };
A.prototype.x = function () {
//do something
};
algo muito diferente ocorre. Na primeira linha, a variável A
é atribuída uma referência a uma função. Em JavaScript, todos os objetos de funções têm uma propriedade prototype por padrão, portanto, não há código separado para criar um objeto A.prototype .
Na segunda linha, A.prototype.x recebe uma referência a uma função. Isso criará uma propriedade x , se não existir, ou atribuirá um novo valor, se existir. Portanto, a diferença com o primeiro exemplo em que a propriedade x do objeto está envolvida na expressão.
Outro exemplo está abaixo. É semelhante ao primeiro (e talvez o que você queria perguntar):
var A = new function () {
this.x = function () {
//do something
};
};
Neste exemplo, o new
operador foi adicionado antes da expressão da função para que a função seja chamada como construtor. Quando chamada com new
, a função this é configurada para referenciar um novo Object cuja [[Prototype]]
propriedade privada é configurada para referenciar o protótipo público do construtor . Portanto, na declaração de atribuição, a x
propriedade será criada nesse novo objeto. Quando chamada como construtora, uma função retorna esse objeto por padrão, portanto, não há necessidade de uma return this;
instrução separada .
Para verificar se A possui uma propriedade x :
console.log(A.x) // function () {
// //do something
// };
Esse é um uso incomum do novo, pois a única maneira de referenciar o construtor é através do A.constructor . Seria muito mais comum fazer:
var A = function () {
this.x = function () {
//do something
};
};
var a = new A();
Outra maneira de obter um resultado semelhante é usar uma expressão de função chamada imediatamente:
var A = (function () {
this.x = function () {
//do something
};
}());
Nesse caso, A
atribua o valor de retorno da chamada da função no lado direito. Aqui, novamente, como isso não está definido na chamada, ele fará referência ao objeto global e this.x
é eficaz window.x
. Como a função não retorna nada, A
terá um valor de undefined
.
Essas diferenças entre as duas abordagens também se manifestam se você estiver serializando e desserializando seus objetos Javascript de / para JSON. Os métodos definidos no protótipo de um objeto não são serializados quando você o serializa, o que pode ser conveniente quando, por exemplo, você deseja serializar apenas as partes de dados de um objeto, mas não os métodos:
var A = function () {
this.objectsOwnProperties = "are serialized";
};
A.prototype.prototypeProperties = "are NOT serialized";
var instance = new A();
console.log(instance.prototypeProperties); // "are NOT serialized"
console.log(JSON.stringify(instance));
// {"objectsOwnProperties":"are serialized"}
Questões relacionadas :
Nota: Pode não haver economia significativa de memória entre as duas abordagens, no entanto, o uso do protótipo para compartilhar métodos e propriedades provavelmente usará menos memória do que cada instância com sua própria cópia.
JavaScript não é uma linguagem de baixo nível. Pode não ser muito valioso pensar em protótipos ou outros padrões de herança como uma maneira de alterar explicitamente a maneira como a memória é alocada.
null
), mas isso é muito diferente da prototype
propriedade - que está nas funções e na qual o protótipo de todas as instâncias é definido quando elas são construídas new
. Não posso acreditar que isso realmente tenha 87
"The language is functional"
Tem certeza de que é isso que significa funcional?
A
como função, e a outra metade é sobre maneiras obscuras e não-ortodoxas de fazer algo simples.
Como outros já disseram na primeira versão, usar "this" resulta em todas as instâncias da classe A com sua própria cópia independente do método da função "x". Enquanto o uso de "protótipo" significa que cada instância da classe A usará a mesma cópia do método "x".
Aqui está um código para mostrar essa diferença sutil:
// x is a method assigned to the object using "this"
var A = function () {
this.x = function () { alert('A'); };
};
A.prototype.updateX = function( value ) {
this.x = function() { alert( value ); }
};
var a1 = new A();
var a2 = new A();
a1.x(); // Displays 'A'
a2.x(); // Also displays 'A'
a1.updateX('Z');
a1.x(); // Displays 'Z'
a2.x(); // Still displays 'A'
// Here x is a method assigned to the object using "prototype"
var B = function () { };
B.prototype.x = function () { alert('B'); };
B.prototype.updateX = function( value ) {
B.prototype.x = function() { alert( value ); }
}
var b1 = new B();
var b2 = new B();
b1.x(); // Displays 'B'
b2.x(); // Also displays 'B'
b1.updateX('Y');
b1.x(); // Displays 'Y'
b2.x(); // Also displays 'Y' because by using prototype we have changed it for all instances
Como outros já mencionaram, existem várias razões para escolher um método ou outro. Minha amostra é apenas para demonstrar claramente a diferença.
this
objeto, que é o proprietário do método. isto é, o método não possui nenhum objeto que seja seu proprietário. Nesse caso, há um this
objeto, conforme mostrado na classe A no exemplo.
Veja estes 2 exemplos:
var A = function() { this.hey = function() { alert('from A') } };
vs.
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
A maioria das pessoas aqui (especialmente as respostas mais bem avaliadas) tentou explicar como elas são diferentes sem explicar POR QUE. Eu acho que isso está errado e se você entender os fundamentos primeiro, a diferença se tornará óbvia. Vamos tentar explicar os fundamentos primeiro ...
a) Uma função é um objeto em JavaScript. CADA objeto no JavaScript obtém uma propriedade interna (o que significa que você não pode acessá-lo como outras propriedades, exceto talvez em navegadores como o Chrome), geralmente chamado de __proto__
(você pode realmente digitar o anyObject.__proto__
Chrome para ver o que ele faz referência. , uma propriedade, nada mais.Uma propriedade em JavaScript = uma variável dentro de um objeto, nada mais.O que as variáveis fazem? Elas apontam para coisas.
Então, o que essa __proto__
propriedade aponta? Bem, geralmente outro objeto (explicaremos o porquê mais tarde). A única maneira de forçar o JavaScript para que a __proto__
propriedade NÃO aponte para outro objeto é usar var newObj = Object.create(null)
. Mesmo se você fizer isso, a __proto__
propriedade AINDA existe como uma propriedade do objeto, mas não aponta para outro objeto, aponta para null
.
Aqui é onde a maioria das pessoas se confunde:
Quando você cria uma nova função no JavaScript (que também é um objeto, lembra?), No momento em que é definida, o JavaScript cria automaticamente uma nova propriedade nessa função chamada prototype
. Tente:
var A = [];
A.prototype // undefined
A = function() {}
A.prototype // {} // got created when function() {} was defined
A.prototype
é TOTALMENTE DIFERENTE da __proto__
propriedade. No nosso exemplo, 'A' agora tem DUAS propriedades chamadas 'protótipo' e __proto__
. Esta é uma grande confusão para as pessoas. prototype
e as __proto__
propriedades não têm relação alguma, são coisas separadas apontando para valores separados.
Você pode se perguntar: Por que o JavaScript possui __proto__
propriedades criadas em todos os objetos? Bem, uma palavra: delegação . Quando você chama uma propriedade em um objeto e o objeto não a possui, o JavaScript procura o objeto referenciado por __proto__
para ver se ele talvez o possua. Se não o possuir, ele examinará a __proto__
propriedade desse objeto e assim por diante ... até a cadeia terminar. Assim, o nome da cadeia de protótipos . Obviamente, se __proto__
não apontar para um objeto e, em vez disso, apontar para null
, com muita sorte, o JavaScript perceberá isso e o retornará undefined
para a propriedade.
Você também pode se perguntar: por que o JavaScript cria uma propriedade chamada prototype
para uma função quando você a define? Porque ele tenta enganar você, sim engane você que funciona como linguagens baseadas em classes.
Vamos continuar com o nosso exemplo e criar um "objeto" de A
:
var a1 = new A();
Há algo acontecendo em segundo plano quando isso aconteceu. a1
é uma variável comum à qual foi atribuído um novo objeto vazio.
O fato de você ter usado o operador new
antes de uma chamada de função A()
fez algo ADICIONAL em segundo plano. A new
palavra-chave criou um novo objeto que agora faz referência a1
e esse objeto está vazio. Aqui está o que está acontecendo adicionalmente:
Dissemos que em cada definição de função há uma nova propriedade criada chamada prototype
(que você pode acessá-la, diferente da __proto__
propriedade) criada? Bem, essa propriedade está sendo usada agora.
Então, agora estamos no ponto em que temos um a1
objeto vazio recém-assado . Dissemos que todos os objetos em JavaScript têm uma __proto__
propriedade interna que aponta para algo ( a1
também possui), seja nulo ou outro objeto. O que o new
operador faz é que ele defina essa __proto__
propriedade para apontar para a prototype
propriedade da função . Leia isso de novo. É basicamente isso:
a1.__proto__ = A.prototype;
Dissemos que A.prototype
nada mais é do que um objeto vazio (a menos que o alteremos para outra coisa antes de definir a1
). Então agora basicamente a1.__proto__
aponta para a mesma coisa A.prototype
, que é esse objeto vazio. Ambos apontam para o mesmo objeto que foi criado quando essa linha aconteceu:
A = function() {} // JS: cool. let's also create A.prototype pointing to empty {}
Agora, há outra coisa acontecendo quando a var a1 = new A()
instrução é processada. Basicamente, A()
é executado e se A é algo como isto:
var A = function() { this.hey = function() { alert('from A') } };
Todas essas coisas lá dentro function() { }
serão executadas. Quando você atinge a this.hey..
linha, this
é alterado para a1
e você obtém o seguinte:
a1.hey = function() { alert('from A') }
Não falarei sobre o porquê de this
alterações, a1
mas esta é uma ótima resposta para saber mais.
Então, para resumir, quando você faz, var a1 = new A()
há três coisas acontecendo em segundo plano:
a1
.a1 = {}
a1.__proto__
A propriedade é atribuída para apontar para a mesma coisa que A.prototype
aponta para (outro objeto vazio {})
A função A()
está sendo executada com this
definido para o novo objeto vazio criado na etapa 1 (leia a resposta que eu referenciei acima sobre o motivo de this
mudar para a1
)
Agora, vamos tentar criar outro objeto:
var a2 = new A();
Os passos 1,2,3 serão repetidos. Você percebe alguma coisa? A palavra-chave é repetir. Etapa 1: a2
será um novo objeto vazio, etapa 2: sua __proto__
propriedade apontará para a mesma coisa A.prototype
e, mais importante, etapa 3: a função A()
é AGAIN executada, o que significa que a2
obterá a hey
propriedade que contém uma função. a1
e a2
tem duas propriedades SEPARATE nomeadas hey
que apontam para 2 funções SEPARATE! Agora temos funções duplicadas nos mesmos dois objetos diferentes fazendo a mesma coisa, oops ... Você pode imaginar as implicações de memória disso se tivermos 1000 objetos criados com new A
, depois de todas as declarações de funções ocuparem mais memória do que algo como o número 2. Então como podemos evitar isso?
Lembra por que a __proto__
propriedade existe em todos os objetos? Para que, se você recuperar a yoMan
propriedade em a1
(que não existe), sua __proto__
propriedade será consultada; se for um objeto (e na maioria dos casos, for), verificará se ela contém yoMan
e, se não, ele consultará o objeto __proto__
etc. etc. Se o fizer, ele pegará esse valor da propriedade e exibirá para você.
Então, alguém decidiu usar esse fato + o fato de que, quando você cria a1
, sua __proto__
propriedade aponta para o mesmo objeto (vazio) A.prototype
para:
var A = function() {}
A.prototype.hey = function() { alert('from prototype') };
Legal! Agora, quando você cria a1
, ele passa novamente por todas as 3 etapas acima e, na etapa 3, não faz nada, pois function A()
não tem nada para executar. E se fizermos:
a1.hey
Ele verá que a1
não contém hey
e verificará seu __proto__
objeto de propriedade para ver se o possui, qual é o caso.
Com essa abordagem, eliminamos a parte da etapa 3, na qual as funções são duplicadas em cada nova criação de objeto. Em vez de a1
e a2
ter uma hey
propriedade separada , agora NENHUM deles a possui. Acho que você já se descobriu agora. Essa é a coisa legal ... se você entender __proto__
e Function.prototype
, perguntas como essas serão bem óbvias.
NOTA: Algumas pessoas tendem a não chamar a propriedade Prototype interna __proto__
, pois usei esse nome na postagem para distingui-lo claramente da Functional.prototype
propriedade como duas coisas diferentes.
__proto__
e .prototype
são coisas totalmente diferentes.
Na maioria dos casos, eles são essencialmente os mesmos, mas a segunda versão economiza memória porque há apenas uma instância da função em vez de uma função separada para cada objeto.
Uma razão para usar o primeiro formulário é acessar "membros privados". Por exemplo:
var A = function () {
var private_var = ...;
this.x = function () {
return private_var;
};
this.setX = function (new_x) {
private_var = new_x;
};
};
Devido às regras de escopo do javascript, private_var está disponível para a função atribuída a this.x, mas não fora do objeto.
O primeiro exemplo altera a interface apenas para esse objeto. O segundo exemplo altera a interface para todos os objetos dessa classe.
x
disponível para todos os objetos cujo protótipo é atribuída uma nova instância A:function B () {}; B.prototype = new A(); var b = new B(); b.x() // Will call A.x if A is defined by first example;
O maior problema com o uso em this
vez de prototype
é que, ao substituir um método, o construtor da classe base ainda fará referência ao método substituído. Considere isto:
BaseClass = function() {
var text = null;
this.setText = function(value) {
text = value + " BaseClass!";
};
this.getText = function() {
return text;
};
this.setText("Hello"); // This always calls BaseClass.setText()
};
SubClass = function() {
// setText is not overridden yet,
// so the constructor calls the superclass' method
BaseClass.call(this);
// Keeping a reference to the superclass' method
var super_setText = this.setText;
// Overriding
this.setText = function(value) {
super_setText.call(this, "SubClass says: " + value);
};
};
SubClass.prototype = new BaseClass();
var subClass = new SubClass();
console.log(subClass.getText()); // Hello BaseClass!
subClass.setText("Hello"); // setText is already overridden
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
versus:
BaseClass = function() {
this.setText("Hello"); // This calls the overridden method
};
BaseClass.prototype.setText = function(value) {
this.text = value + " BaseClass!";
};
BaseClass.prototype.getText = function() {
return this.text;
};
SubClass = function() {
// setText is already overridden, so this works as expected
BaseClass.call(this);
};
SubClass.prototype = new BaseClass();
SubClass.prototype.setText = function(value) {
BaseClass.prototype.setText.call(this, "SubClass says: " + value);
};
var subClass = new SubClass();
console.log(subClass.getText()); // SubClass says: Hello BaseClass!
Se você acha que isso não é um problema, depende se você pode viver sem variáveis privadas e se possui experiência suficiente para conhecer um vazamento ao vê-lo. Além disso, ter que colocar a lógica do construtor após as definições do método é inconveniente.
var A = function (param1) {
var privateVar = null; // Private variable
// Calling this.setPrivateVar(param1) here would be an error
this.setPrivateVar = function (value) {
privateVar = value;
console.log("setPrivateVar value set to: " + value);
// param1 is still here, possible memory leak
console.log("setPrivateVar has param1: " + param1);
};
// The constructor logic starts here possibly after
// many lines of code that define methods
this.setPrivateVar(param1); // This is valid
};
var a = new A(0);
// setPrivateVar value set to: 0
// setPrivateVar has param1: 0
a.setPrivateVar(1);
//setPrivateVar value set to: 1
//setPrivateVar has param1: 0
versus:
var A = function (param1) {
this.setPublicVar(param1); // This is valid
};
A.prototype.setPublicVar = function (value) {
this.publicVar = value; // No private variable
};
var a = new A(0);
a.setPublicVar(1);
console.log(a.publicVar); // 1
Todo objeto está vinculado a um objeto de protótipo. Ao tentar acessar uma propriedade que não existe, o JavaScript procurará no objeto de protótipo do objeto e a retornará, se existir.
A prototype
propriedade de um construtor de função refere-se ao objeto de protótipo de todas as instâncias criadas com essa função ao usar new
.
No seu primeiro exemplo, você está adicionando uma propriedade x
a cada instância criada com a A
função
var A = function () {
this.x = function () {
//do something
};
};
var a = new A(); // constructor function gets executed
// newly created object gets an 'x' property
// which is a function
a.x(); // and can be called like this
No segundo exemplo, você está adicionando uma propriedade ao objeto de protótipo para o qual todas as instâncias criadas A
apontam.
var A = function () { };
A.prototype.x = function () {
//do something
};
var a = new A(); // constructor function gets executed
// which does nothing in this example
a.x(); // you are trying to access the 'x' property of an instance of 'A'
// which does not exist
// so JavaScript looks for that property in the prototype object
// that was defined using the 'prototype' property of the constructor
Em conclusão, no primeiro exemplo, uma cópia da função é atribuída a cada instância . No segundo exemplo, uma única cópia da função é compartilhada por todas as instâncias .
Qual é a diferença? => Muito.
Eu acho que a this
versão é usada para ativar o encapsulamento, ou seja, ocultar dados. Ajuda a manipular variáveis privadas.
Vejamos o seguinte exemplo:
var AdultPerson = function() {
var age;
this.setAge = function(val) {
// some housekeeping
age = val >= 18 && val;
};
this.getAge = function() {
return age;
};
this.isValid = function() {
return !!age;
};
};
Agora, a prototype
estrutura pode ser aplicada da seguinte maneira:
Adultos diferentes têm idades diferentes, mas todos têm os mesmos direitos.
Então, nós o adicionamos usando protótipo, e não isso.
AdultPerson.prototype.getRights = function() {
// Should be valid
return this.isValid() && ['Booze', 'Drive'];
};
Vamos analisar a implementação agora.
var p1 = new AdultPerson;
p1.setAge(12); // ( age = false )
console.log(p1.getRights()); // false ( Kid alert! )
p1.setAge(19); // ( age = 19 )
console.log(p1.getRights()); // ['Booze', 'Drive'] ( Welcome AdultPerson )
var p2 = new AdultPerson;
p2.setAge(45);
console.log(p2.getRights()); // The same getRights() method, *** not a new copy of it ***
Espero que isto ajude.
Protótipo é o modelo da classe; que se aplica a todas as instâncias futuras dele. Considerando que esta é a instância específica do objeto.
Eu sei que isso foi respondido até a morte, mas eu gostaria de mostrar um exemplo real de diferenças de velocidade.
Aqui, estamos criando 2.000.000 de novos objetos com um print
método no Chrome. Estamos armazenando todos os objetos em uma matriz. A colocação print
do protótipo leva cerca de 1/2 do tempo.
Deixe-me dar uma resposta mais abrangente que aprendi durante um curso de treinamento em JavaScript.
A maioria das respostas já mencionou a diferença, ou seja, ao prototipar a função é compartilhada com todas as instâncias (futuras). Considerando que declarar a função na classe criará uma cópia para cada instância.
Em geral, não há certo ou errado, é mais uma questão de gosto ou uma decisão de design, dependendo de suas necessidades. O protótipo, no entanto, é a técnica usada para desenvolver de maneira orientada a objetos, como espero que você veja no final desta resposta.
Você mostrou dois padrões em sua pergunta. Vou tentar explicar mais duas e tentarei explicar as diferenças, se relevante. Sinta-se livre para editar / estender. Em todos os exemplos, trata-se de um objeto de carro que possui um local e pode se mover.
Não tenho certeza se esse padrão ainda é relevante hoje em dia, mas existe. E é bom saber sobre isso. Você simplesmente passa um objeto e uma propriedade para a função decoradora. O decorador retorna o objeto com propriedade e método.
var carlike = function(obj, loc) {
obj.loc = loc;
obj.move = function() {
obj.loc++;
};
return obj;
};
var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();
Uma função em JavaScript é um objeto especializado. Além de ser invocada, uma função pode armazenar propriedades como qualquer outro objeto.
Nesse caso, Car
é uma função ( também pense em objeto ) que pode ser invocada como você costuma fazer. Possui uma propriedade methods
(que é um objeto com uma move
função). Quando Car
é chamada, a extend
função é chamada, o que faz alguma mágica e estende a Car
função (objeto de reflexão) com os métodos definidos dentro methods
.
Este exemplo, embora diferente, se aproxima do primeiro exemplo da pergunta.
var Car = function(loc) {
var obj = {loc: loc};
extend(obj, Car.methods);
return obj;
};
Car.methods = {
move : function() {
this.loc++;
}
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
Os dois primeiros padrões permitem uma discussão sobre o uso de técnicas para definir métodos compartilhados ou o uso de métodos definidos em linha no corpo do construtor. Nos dois casos, cada instância tem sua própria move
função.
O padrão prototípico não se presta bem ao mesmo exame, porque o compartilhamento de funções por meio de uma delegação de protótipo é o próprio objetivo do padrão prototípico. Como outros apontaram, espera-se que tenha uma melhor pegada de memória.
No entanto, há um ponto interessante a saber: todo prototype
objeto tem uma propriedade de conveniência constructor
, que aponta para a função (objeto de reflexão) à qual ele foi anexado.
Em relação às três últimas linhas:
Neste exemplo, Car
vincula-se ao prototype
objeto, que vincula-se constructor
a Car
ele próprio, ou seja, Car.prototype.constructor
éCar
ele próprio. Isso permite que você descubra qual função do construtor construiu um determinado objeto.
amy.constructor
A pesquisa de falha e, portanto, é delegada para Car.prototype
, que possui a propriedade construtora. E assim amy.constructor
é Car
.
Além disso, amy
é um instanceof
Car
. O instanceof
operador trabalha verificando se o objeto protótipo do operando direito ( Car
) pode ser encontrado em qualquer lugar da amy
cadeia protótipo ( ) do operando esquerdo .
var Car = function(loc) {
var obj = Object.create(Car.prototype);
obj.loc = loc;
return obj;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();
console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);
Alguns desenvolvedores podem ficar confusos no começo. Veja o exemplo abaixo:
var Dog = function() {
return {legs: 4, bark: alert};
};
var fido = Dog();
console.log(fido instanceof Dog);
O instanceof
operador retorna false
, porque Dog
o protótipo não pode ser encontrado em nenhum lugar da fido
cadeia de protótipos. fido
é um objeto simples criado com um literal de objeto, ou seja, apenas delega paraObject.prototype
.
Essa é realmente apenas outra forma do padrão prototípico de forma simplificada e mais familiar para quem programa em Java, por exemplo, uma vez que usa o new
construtor.
Ele realmente faz o mesmo que no padrão prototípico, é apenas uma sobreposição sintática de açúcar do padrão prototípico.
No entanto, a principal diferença é que há otimizações implementadas nos mecanismos JavaScript que só se aplicam ao usar o padrão pseudoclássico. Pense no padrão pseudoclássico uma versão provavelmente mais rápida do padrão prototípico; as relações de objeto nos dois exemplos são as mesmas.
var Car = function(loc) {
this.loc = loc;
};
Car.prototype.move = function() {
this.loc++;
};
var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();
Finalmente, não deve ser muito difícil perceber como a programação orientada a objetos pode ser feita. Existem duas seções.
Uma seção que define propriedades / métodos comuns no protótipo (cadeia).
E outra seção em que você coloca as definições que distinguem os objetos um do outro ( loc
variável nos exemplos).
É isso que nos permite aplicar conceitos como superclasse ou subclasse em JavaScript.
Sinta-se livre para adicionar ou editar. Mais uma vez completo, talvez eu possa fazer deste um wiki da comunidade.
Acredito que @Matthew Crumley está certo. Eles são funcionalmente , se não estruturalmente, equivalentes. Se você usar o Firebug para examinar os objetos criados usando new
, poderá ver que eles são iguais. No entanto, minha preferência seria a seguinte. Eu estou supondo que parece mais com o que estou acostumado em C # / Java. Ou seja, defina a classe, defina os campos, construtor e métodos.
var A = function() {};
A.prototype = {
_instance_var: 0,
initialize: function(v) { this._instance_var = v; },
x: function() { alert(this._instance_var); }
};
EDIT Não quis dizer que o escopo da variável era privado, apenas estava tentando ilustrar como defino minhas classes em javascript. O nome da variável foi alterado para refletir isso.
initialize
e x methods do not refer to the
_instance_var` em uma A
instância, mas em uma global. Use this._instance_var
se você pretendia usar a _instance_var
propriedade de uma A
instância.
Conforme discutido em outras respostas, é realmente uma consideração de desempenho porque a função no protótipo é compartilhada com todas as instanciações - em vez da função que está sendo criada para cada instanciação.
Eu montei um jsperf para mostrar isso. Há uma diferença dramática no tempo necessário para instanciar a classe, embora seja realmente relevante apenas se você estiver criando muitas instâncias.