Recentemente, estou assistindo "JavaScript Advanced Programming" (segunda edição)
Criação de objetos em javascript
• Modo de fábrica
• Modo construtor
• Modo de protótipo
• Combinar o padrão de construtor e protótipo
• Modo dinâmico do protótipo
A maioria dos idiomas orientados a objetos tem o conceito de classe, através do qual vários objetos com os mesmos métodos e atributos podem ser criados. Embora tecnicamente, o JavaScript seja uma linguagem orientada a objetos, o JavaScript não possui o conceito de classes, tudo é um objeto. Qualquer objeto é uma instância de um determinado tipo de referência e é criado através dos tipos de referência existentes; O tipo de referência pode ser nativo ou personalizado. Os tipos de referência nativos são: objeto, matriz, dados, regexp, função. ! Um tipo de referência é uma estrutura de dados que organiza dados e funções juntos, geralmente chamado de classe. Em JavaScript que não possui o conceito de classe, o problema que precisa ser resolvido é como criar objetos com eficiência.
1.1.0. Métodos gerais para criar objetos
var pessoa = {}; // A representação literal do objeto é equivalente a var pessoa = new objCect (); pessoa.name = 'evansdiy'; pessoa.age = '22'; pessoa.friends = ['Ajiao', 'Tiantian', 'Pangzi']; Person.Logname = function () {console.log (this.name);}Com base no tipo de referência do objeto, um objeto é criado, que contém quatro propriedades, uma das quais é um método. Se você precisar de muitas instâncias como a pessoa, haverá muito código duplicado.
1.1.1. Modelo de fábrica
Crie um objeto com uma função que possa conter os detalhes do objeto e retornar o objeto.
função pessoa (nome, idade, amigos) {var o = {nome: nome, idade: idade: amigos: amigos, logname: function () {console.log (this.name); }}; retornar o;} var pessoa1 = pessoa ('evansdiy', '22', ['ajiao', 'tiantian', 'pangzi']);Toda vez que a função da pessoa é chamada, um novo objeto é criado através do objeto O dentro da função e depois retornado. Além disso, esse objeto interno o existe para criar um novo objeto não tem outro objetivo. Além disso, é impossível determinar o tipo de objeto criado pelo modo de fábrica.
1.1.2. Modo construtor
função pessoa (nome, idade, trabalho) {this.name = name; this.age = idade; this.Job = Job; this.Logname = function () {console.log (this.name); }} // Crie uma instância de pessoa através do novo operador var person1 = new Pessoa ('Boy-A', '22', 'Worker'); var Person2 = New Pessoa ('Girl-B', '23', 'Professor'); Person1.Logname (); //boy-aperson2.Logname (); // Girl-AComparando o modo de fábrica, podemos descobrir que não há necessidade de criar objetos intermediários aqui, não há retorno. Além disso, a instância do construtor pode ser identificada como um tipo específico, que resolve o problema do reconhecimento de objetos (verificando o atributo construtor da instância ou usando a instância do operador para verificar se a instância é criada por um construtor).
console.log (Person1.Constructor == Person); // Construtor está localizado no protótipo do construtor e aponta para o construtor, e o resultado é verdadeiro
Console.log (Pessoa1 Instância de pessoa); // Use a instância do operador para determinar se a Pessoa1 é uma instância da pessoa do construtor, mas o padrão do construtor também tem seus próprios problemas. De fato, o método de nome de log será recriado uma vez em cada instância. Deve -se notar que os métodos criados por instanciação não são iguais e o código a seguir será falso:
console.log (Person1.Logname == Person2.Logname); // FALSE Podemos mover o método para fora do construtor (mudado para uma função global) para resolver esse problema:
function logname () {console.log (this.name);} função logage () {console.log (this.age);}No entanto, as funções globais criadas globalmente só podem ser chamadas por instâncias criadas pela pessoa, o que é um pouco irrealista; Se houver muitos métodos, eles ainda precisam ser definidos um por um, sem encapsulamento.
1.1.3. Modo de protótipo
Cada função no JavaScript contém um ponteiro para o atributo protótipo (a maioria dos navegadores pode acessá -lo através do atributo interno __proto__), um atributo de protótipo é um objeto que contém propriedades e métodos compartilhados por todas as instâncias criadas por um determinado tipo de referência.
function pessoa () {} pessoa.name = 'evansdiy'; pessoa.prototype.friends = ['ajiao', 'jianjian', 'pangzi']; pessoa.prototype.Logname = function () {consol.log.log (this.name);} varson1 = new pessoa ();O código acima faz as estas:
1. Defina uma pessoa construtora. A função da pessoa obtém automaticamente uma propriedade de protótipo. Esta propriedade contém apenas uma propriedade construtora apontando para a pessoa por padrão;
2. Adicione três atributos através da pessoa. Prototipo, um dos quais é usado como um método;
3. Crie uma instância de pessoa e ligue para o método logname () na instância. !
O que você precisa observar aqui é o processo de chamada do método logname ():
1. Procure o método logname () na instância de pessoa1 e descobriu que não existe esse método, então eu voltei ao protótipo de pessoa1
2. Procure o método logame () no protótipo da Pessoa1. Existe esse método. Portanto, chamamos esse método com base em esse processo de pesquisa. Podemos impedir que a instância acesse o atributo de mesmo nome no protótipo, definindo o mesmo nome do atributo no protótipo na instância. Deve-se notar que isso não excluirá o mesmo atributo de nome no protótipo, mas apenas impedirá o acesso à instância.
var pessoa2 = new Person ();
pessoa2.name = 'laocai'; Se não precisarmos mais de propriedades na instância, podemos excluí -la através do operador Excluir.
excluir pessoa.Name; Use o loop for-in para enumerar todos os atributos que uma instância pode acessar (independentemente de existir o atributo na instância ou no protótipo):
para (i em pessoa1) {console.log (i);}Ao mesmo tempo, você também pode usar o método HASOWNPROPERTY () para determinar se existe uma determinada propriedade na instância ou no protótipo. Somente quando a propriedade existir na instância será verdadeira devolvida:
console.log (Person1.HasownProperty ('nome')); // true! O HasownProperty vem do protótipo do objeto e é a única maneira de JavaScript para não procurar a cadeia de protótipos ao processar propriedades. [Via Javascript Secret Garden] Além disso, você também pode usar o método Operator e HasOwnProperty () para determinar se existe uma determinada propriedade na instância ou no protótipo:
Console.log (('Friends' em Person1) &&! Person1.HasownProperty ('Friends')); primeiro determine se a Pessoa1 pode acessar a propriedade Friends. Se possível, determine se essa propriedade existe na instância (observe o anterior!). Se não existir na instância, significa que essa propriedade existe no protótipo. Como mencionado anteriormente, o protótipo também é um objeto, para que possamos escrever o protótipo usando a representação literal do objeto. O método de escrita anterior de adicionar código ao protótipo pode ser modificado para:
Person.Prototype = {Nome: 'Evansdiy', Amigos: ['Ajiao', 'Jianjian', 'Pangzi'], LogName: function () {console.log (this.name); }}Como a sintaxe literal do objeto reescreve todo o protótipo protótipo, o atributo construtor obtido por padrão ao criar o construtor apontará para o construtor de objetos:
// Após o objeto literal reescrever o protótipo
console.log (Person1.Constructor); // Objeto No entanto, o operador da instância do resultado ainda retornará o resultado desejado:
// Após o objeto literal reescrever o protótipo
Console.log (Pessoa1 Instância de pessoa); // Verdadeiro, é claro, você pode definir manualmente o valor do construtor no protótipo para resolver esse problema.
Person.prototype = {Construtor: Pessoa, ......}Se o objeto de protótipo for modificado após a criação da instância do objeto, a modificação do protótipo será refletida imediatamente em todas as instâncias do objeto:
function pessoa () {}; var pessoa1 = new Person (); Pessoa.prototype.name = 'Evansdiy'; Console.log (Person1.name); // 'evansdiy'A conexão entre uma instância e um protótipo é apenas um ponteiro, não uma cópia do protótipo. O protótipo é na verdade um processo de pesquisa. Quaisquer modificações feitas no objeto de protótipo serão refletidas em todas as instâncias de objetos, mesmo que o protótipo seja modificado após a criação da instância. E se o objeto de protótipo for reescrever após criar uma instância do objeto?
function pessoa () {}; var pessoa1 = new Person1 (); // A instância criada refere -se ao protótipo original // O protótipo PERSON.Prototype = {Friends: ['Ajiao', 'Jianjian', 'Pangzi']} varson2 = nova pessoa (); // essa instância refere -se ao protipopy. console.log (Person1.friends);O código acima terá um erro indefinido quando for executado na última linha. Se usarmos para inumerar as propriedades acessíveis em Pessoa1, descobriremos que não há nada por dentro, mas a pessoa2 pode acessar o atributo de amigos no protótipo. ! Reescrever o protótipo corta a conexão entre o protótipo existente e todas as instâncias de objetos criadas antes. O protótipo da instância do objeto criado antes ainda está lá, mas é antigo.
// Ao criar Pessoa1, o objeto de protótipo ainda não foi reescrito. Portanto, o construtor no objeto de protótipo ainda é o PERSON () console.log (Person1.Constructor); // Pessoa () // Mas o construtor de Pessoas2 aponta para objeto () console.log (Person2.Constructor); // objeto ()
Deve -se notar que o padrão de protótipo ignora o processo de passagem de parâmetros para o construtor e todas as instâncias obtêm o mesmo valor de atributo. Ao mesmo tempo, há um grande problema com o padrão de protótipo, ou seja, o valor do tipo de referência no objeto de protótipo será compartilhado por todas as instâncias, e a modificação do valor do tipo de referência também será refletida em todas as instâncias do objeto.
function pessoa () {}; pessoa.prototype = {Friends: ['Ajiao', 'Tiantian', 'Pangzi']} var Person1 = new Person (); var pessoa2 = new Person (); Pessoa1.friends.push ('Laocai'); Console.Log (ASSON2.MAIRM);Modificar o valor do tipo de referência de Pessoa 1 amigos significa que os amigos pessoalmente2 também mudarão. De fato, os amigos salvos no protótipo são na verdade apenas um ponteiro para o valor dos amigos na pilha (o comprimento deste ponteiro é fixo e salvo na pilha). Quando uma instância acessa o valor do tipo de referência através do protótipo, ele também é acessado por ponteiro em vez de acessar a cópia na respectiva instância (essa cópia não existe).
1.1.4. Crie objetos em combinação com o padrão de construtor e protótipo
Combinando as vantagens do modo construtor e protótipo, compensando suas respectivas deficiências, usando construtores para passar os parâmetros de inicialização, definir atributos de instância neles e usar protótipos para definir métodos comuns e atributos públicos. Este modo é mais amplamente utilizado.
função pessoa (nome, idade) {this.name = name; this.age = idade; this.friends = ['ajiao', 'jianjian', 'pangzi'];} pessoa.prototype = {construtor: pessoa, logname: function () {console.log (this.name); }} var pessoa1 = new Pessoa ('evansdiy', '22'); var pessoa2 = nova pessoa ('amy', '21'); pessoa1.Logname (); // 'evansdiy'person1.friends.push (' haixao '); console.log (pessoa2.friends.lgen); // 31.1.5. Modo dinâmico de protótipo
O modo protótipo dinâmico encapsula todas as informações necessárias no construtor e usa a instrução IF para determinar se existe uma determinada propriedade no protótipo. Se não existir (quando o construtor for chamado pela primeira vez), execute o código de inicialização do protótipo dentro da instrução IF.
função pessoa (nome, idade) {this.name = name; this.age = idade; if (typeof this.Logname! = 'function') {Person.prototype.Logname = function () {console.log (this.name); }; Pessoa.prototype.logage = function () {console.log (this.age); }; }; };} var pessoa1 = new Person ('evansdiy', '22'); // O construtor foi chamado pela primeira vez, e o protótipo foi modificado no momento. var pessoa2 = nova pessoa ('amy', '21'); // o método logname () já existe e o protótipo não será modificado novamenteDeve -se notar que esse padrão não pode usar a sintaxe literal do objeto para gravar objetos de protótipo (isso substituirá os objetos do protótipo). Se o protótipo for reescrito, o protótipo objeto acessível à primeira instância criado pelo construtor não conterá as propriedades do objeto do protótipo na instrução IF.
função pessoa (nome, idade) {this.name = name; this.age = idade; if (typeof this.Logname! = 'function') {Person.prototype = {logname: function () {console.log (this.name); }, logage: function () {console.log (this.age); }}}};} var person1 = new Person ('evansdiy', '22'); var pessoa2 = new Person ('amy', '21'); pessoa2.Logname (); // 'amy'person1.Logname (); // LogName () não existeDeve -se notar que cada modelo possui seus próprios cenários de aplicativos e não importa suas vantagens e desvantagens.
A análise acima de vários padrões de criação de objetos no JavaScript é todo o conteúdo que compartilho com você. Espero que possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.