1. Use variáveis globais para salvar casos únicos
Esta é a maneira mais fácil de implementá -lo
function Person () {this.createTime = new Date (); } var instance = new Person (); function getInstance () {retorna instância; }Ao carregar este JS, um objeto de pessoa é criado e salvo na variável global da instância. Este objeto é tomado toda vez que é usado. Se você não o usou uma vez, o objeto que você criou é desperdiçado, podemos otimizá -lo.
função de instância var getInstance () {if (! Instância) {instance = new Person (); } Instância de retorno; }Dessa forma, o objeto é criado apenas quando é usado pela primeira vez.
A desvantagem desse método é que a instância é uma variável global. Quando várias pessoas cooperam ou o ciclo de desenvolvimento é relativamente longo, é difícil garantir que essa instância não seja modificada ou substituída por outros códigos. É muito provável que, quando a chamada é chamada, constata -se que a instância não é um objeto de pessoa.
Vamos considerar o uso de fechamentos para encapsular a instância, para que não seja mais uma variável global para resolver esse problema.
2. Objeto de criação de fechamento
var getInstance () {var instance; retornar function () {if (! instance) {instance = new Person (); } Instância de retorno; }} ();Dessa forma, a instância é encapsulada e não há necessidade de se preocupar em ser modificado.
Agora você pode obter um singleton através da função getInstance (). Nova pergunta, se eu criar um objeto através de nova pessoa (), ainda recebo vários objetos, e o JavaScript não pode privatizar o construtor como Java. Então, como podemos fazer os objetos que são novos várias vezes ser uma instância?
3. Instância de cache de atributo estático do construtor
Veja o código primeiro
function Person () {// Se a instância tiver sido armazenada em cache, ele retornará diretamente a instância em cache se (tipoof pessoa.Instance === 'Object') {return Person.instance; } this.createTime = new Date (); // em cache de instância person.instance = this; devolver isso; }A partir do código, podemos ver que, na primeira vez, a condição de se retorna falsa, cairá, inicializará o objeto e salve o objeto para a pessoa estática Pessoa.Instance.
A segunda vez nova, a condição de se retorna true, retorna diretamente a pessoa.instance e o código inicializado não será atingido. Portanto, não importa quantas vezes novas, o objeto retornado é o primeiro objeto criado.
As desvantagens desse método são as mesmas que as do método um. Person.instance também é uma propriedade pública e pode ser modificada.
Vamos nos referir ao método 2. Usando um fechamento para encapsular alguém pode resolver o problema
4. Reescreva o construtor
Esse método precisa usar o fechamento, mas não pode ser tão simples quanto o método dois. Precisamos substituir o construtor.
function Person () {// Instância em cache var instância = this; this.createTime = new Date (); // Reescreva o construtor pessoa = function () {retorna instância; }}A primeira vez que nova é chamada, o construtor original é em cache primeiro e depois inicializado, e o construtor é substituído. Quando novo no futuro, o construtor original nunca será chamado, e o construtor de reescrita só pode ser chamado, e essa função sempre retorna a instância em cache.
O método acima parece estar bem, mas durante o teste a seguir, você pode encontrar o problema
// Adicionar atributo Person.prototype.prop1 = true; var p1 = new Person (); // Depois de criar o objeto de inicialização, adicione o atributo Person.prototype.prop2 = true; var p2 = nova pessoa (); // iniciar o console de teste.log (p1.prop1); // o resultado é o verdadeiro console.log (p2.prop1); // o resultado é o verdadeiro console.log (p1.prop2); // o resultado é um console indefinido (p2.Pr (p2.Pr (p2.Prop2); // o resultado é o console indevido.Og (p2.Pin (p2.Pr (p2.Prog2); console.log (p1.Constructor === Pessoa); // O resultado é falso console.log (p2.Constructor === Person); // O resultado é falso
Os resultados esperados devem ser verdadeiros.
Analise o código de teste acima
Pessoa.prototype.prop1 = true; Adiciona o atributo Prop1 no protótipo do construtor original e atribui um valor.
Depois de executar var p1 = new pessoa ();, o construtor da pessoa foi reescrito
Portanto, PERSON.PROTOTYPE.PROP2 = true; Adiciona a propriedade Prop2 no novo protótipo.
var p2 = nova pessoa (); P2 e P1 são na verdade o mesmo objeto, ou seja, o objeto criado pelo construtor original
Portanto, P1 e P2 têm a propriedade Prop1, mas não há propriedade Prop2
Da mesma forma, o construtor de P1 e P2 também aponta para o construtor original, e a pessoa não é mais a função original neste momento.
Para funcionar conforme o esperado, algumas modificações podem ser alcançadas
function Person () {// Instância em cache var instância = this; // reescreva o construtor de construtor = function () {retorna instância; } // reserve o protótipo atributo Person.prototype = this; // instância = new Person (); // Redefina a instância de referência do construtor.Constructor = Pessoa; // Outra instância de inicialização.CreateTime = new Date (); instância de retorno; }Execute o código de teste anterior e o resultado é verdadeiro.
5. Carregamento preguiçoso:
Em projetos grandes ou complexos, ele desempenha uma função de otimização: componentes caros, mas raramente usados, podem ser envolvidos em singletons de carregamento preguiçoso, programas de exemplo:
/ * Singleton com membros privados, Etapa 3. publicMethod1: function () {...}, publicMethod2: function (args) {...}};}) ();/ * esqueleto geral para um singleton de carregamento preguiçoso, etapa 1. privateattribute2 = [1, 2, 3]; Lazy Loading Singleton, Etapa 2. (function () {var unceliStance; // atributo privado que contém a única instância. function construtor () {// Todo o código singleton normal vai aqui. ...} retornar {getInstance: function () {if (! UselInstent) {// instantiate somente se a instância não existir.6. Use Branch Singleton:
O código para um ambiente específico pode ser envolvido em um Singleton ramificado, programa de amostra:
/ * SimpxhrFactory Singleton, Etapa 1. */Var simpexhrFactory = (function () {// Os três ramificações. Var padrão = {createxhrobject: function () {return XmlHttPrequest ();}}; var ActiveXNew = {CrerexHrobject: function (); {); }}; Xmlhttprequest (); Branch, experimente o Método; ActiveXold.CreatExhrobject ();