1. Utilisez des variables globales pour enregistrer des cas uniques
C'est le moyen le plus simple de le mettre en œuvre
fonction personne () {this.createtime = new Date (); } var instance = new personne (); function getInstance () {return instance; }Lors du chargement de ce js, un objet personne est créé et enregistré dans la variable globale d'instance. Cet objet est pris à chaque fois qu'il est utilisé. Si vous ne l'avez pas utilisé une fois, l'objet que vous avez créé est gaspillé, nous pouvons l'optimiser.
var d'instance fonction getInstance () {if (! instance) {instance = new personne (); } return instance; }De cette façon, l'objet n'est créé que lorsqu'il est utilisé pour la première fois.
L'inconvénient de cette méthode est que l'instance est une variable globale. Lorsque plusieurs personnes coopèrent ou que le cycle de développement est relativement long, il est difficile de s'assurer que l'instance ne sera pas modifiée ou écrasée par d'autres codes. Il est très probable que lorsque l'appel est appelé, il est constaté que l'instance n'est pas du tout un objet de personne.
Envisageons d'utiliser des fermetures pour encapsuler l'instance afin qu'il ne soit plus une variable globale pour résoudre ce problème.
2. Objet de création de fermeture
var getInstance () {var instance; return function () {if (! instance) {instance = new personne (); } return instance; }} ();De cette façon, l'instance est encapsulée et il n'est pas nécessaire de s'inquiéter d'être modifié.
Vous pouvez maintenant obtenir un singleton via la fonction getInstance (). Nouvelle question, si je crée un objet via une nouvelle personne (), j'obtiens toujours plusieurs objets, et JavaScript ne peut pas privatiser le constructeur comme Java. Alors, comment pouvons-nous faire en sorte que les objets qui sont nouveaux plusieurs fois soient une instance?
3. Instance de cache d'attribut statique du constructeur
Regardez d'abord le code
function Person () {// Si l'instance a été mise en cache, elle renverra directement l'instance en cache if (typeof personne.instance === 'objet') {return personne.instance; } this.createtime = new Date (); // Instance cache Person.instance = this; retourner ceci; }À partir du code, nous pouvons voir que la première fois, la condition, la condition de renvoie false, baissera, initialisera l'objet, puis enregistrer l'objet à la propriété statique Person.instance.
La deuxième fois nouvelle, l'état de If Retourne True, renvoie directement Person.instance et le code initialisé ne sera pas étendu. Donc, peu importe le nombre de fois nouveau, l'objet retourné est le premier objet créé.
Les inconvénients de cette méthode sont les mêmes que ceux de la méthode un. Person.Instance est également une propriété publique et peut être modifiée.
Passons à la méthode 2. L'utilisation d'une fermeture pour encapsuler une peut résoudre le problème
4. Réécrire le constructeur
Cette méthode doit utiliser des fermetures, mais elle ne peut pas être aussi simple que la méthode deux. Nous devons remplacer le constructeur.
function Person () {// Instance cache var instance = this; this.CreateTime = new Date (); // Réécrivez le constructeur personne = fonction () {return instance; }}La première fois que la nouvelle est appelée, le constructeur d'origine est d'abord mis en cache, puis initialisé, et le constructeur est remplacé. Lorsqu'il est nouveau dans le futur, le constructeur d'origine ne sera jamais appelé, et le constructeur de réécriture ne peut être appelé que, et cette fonction renvoie toujours l'instance mise en cache.
La méthode ci-dessus semble être bien, mais grâce au test suivant, vous pouvez trouver le problème
// Ajouter un attribut Person.prototype.prop1 = true; var p1 = new personne (); // Après avoir créé l'objet d'initialisation, ajoutez l'attribut Person.prototype.prop2 = true; var p2 = new personne (); // Démarrer le test console.log (p1.prop1); // le résultat est True Console.log (p2.prop1); // le résultat est True Console.log (p1.prop2); // le résultat est un non-défini console.log (p2.prop2); // le résultat est un non-défini console.log (p2.prop2); // console.log (p1.constructor === personne); // le résultat est false console.log (p2.Constructor === personne); // le résultat est faux
Les résultats attendus devraient être vrais.
Analyser le code de test ci-dessus
Personne.prototype.prop1 = true; Ajoute l'attribut Prop1 sous le prototype du constructeur d'origine et attribue une valeur.
Après avoir exécuté var p1 = new personne ();, le constructeur de la personne a été réécrit
Par conséquent, personne.prototype.prop2 = true; Ajoute la propriété Prop2 sous le nouveau prototype.
var p2 = new personne (); P2 et P1 sont en fait le même objet, c'est-à-dire l'objet créé par le constructeur d'origine
Donc, P1 et P2 ont la propriété Prop1, mais il n'y a pas de propriété Prop2
De même, le constructeur de P1 et P2 pointe également vers le constructeur d'origine, et la personne n'est plus la fonction d'origine pour le moment.
Afin de fonctionner comme prévu, certaines modifications peuvent être réalisées
function Person () {// Instance cache var instance = this; // réécriture du constructeur personne = function () {return instance; } // réserve le prototype d'attribut Person.prototype = this; // instance = new personne (); // Réinitialise l'instance de référence du constructeur.Constructor = personne; // autre instance d'initialisation.CreateTime = new Date (); retour d'instance; }Exécutez le code de test précédent et le résultat est vrai.
5. Chargement paresseux:
Dans les projets grands ou complexes, il joue un rôle d'optimisation: les composants qui sont chers mais rarement utilisés peuvent être enveloppés dans des singletons de chargement paresseux, des exemples de programmes:
/ * Singleton avec des membres privés, étape 3. * / MyNamespace.Singleton = (function () {// membres privés. publicMethod1: function () {...}, publicMethod2: function (args) {...}};}) (); / * squelette général pour un singleton de chargement paresseux, étape 1. * / MyNamespace.Singleton = (function () {function constructor () {// tout le code normal va ici. // privateattribute2 = [1, 2, 3]; fonction privateMethod1 () {...} privateMethod2 (args) {...} return {// public. LAZY LOCKING SINGLETON, Étape 2. * / MyNamespace.Singleton = (Function () {Function Constructor () {// Tout le code Singleton normal va ici. ...} return {getInstance: function () {// Control Code va ici.}}}) (); / * General Skeleton pour un lossage de Lazy, étape 3. (function () {var uniqueInstance; // Attribut privé qui maintient l'instance unique. Function constructor () {// Tout le code singleton normal va ici. ...} return {getInstance: function () {if (! uniqueInstance) {// instanciate uniquement si l'instance n'existe pas6. Utilisez Branch Singleton:
Le code pour un environnement spécifique peut être enveloppé dans un singleton ramifié, un exemple de programme:
/ * Simplexhrfactory singleton, étape 1. * / Var simplexhrfactory = (function () {// Les trois branches. Var standard = {createExhRobject: function () {return new XmlHttpRequest ();}}; var activexnew = {createExhRobject: function () {return new ActiveXObject ('msxml2.xmlhttp');}}; var standard = {CreatExhRobject: function () {return xmlhttprequest ();}}; ActiveXObject('Microsoft.XMLHTTP'); } }; // To assign the branch, try each method; return whatever doesn't fail. var testObject; try { testObject = standard.createXhrObject(); return standard; // Return this if no error was thrown. } catch(e) { try { testObject = activeXNew.createXhrObject(); return activeXNew; // Return si aucune erreur a été lancée.