2011-09-23 5 views
2

Contexte« Faking » un JavaScript Constructor

Je travaille sur l'amélioration de mes compétences JavaScript et je suis en apprendre davantage sur le prototypage. Je veux mieux comprendre le code dans cette question et toutes les limitations ou les problèmes avec elle. Une chose qui n'a pas été évidente est la définition de constructeurs plus complexes qui font plus qu'une simple initialisation. Ce que je veux faire est d'avoir une classe qui appelle un service web quand il est créé sans avoir besoin d'appeler une méthode juste après l'initialisation. Ce que j'ai fait a été de créer une propriété et d'y assigner une méthode anonyme auto-appelante. Cela semble fonctionner comme je le veux, mais je ne sais pas s'il y a une meilleure approche.

Le code

function AsyncOrderLine(productID) { 

    var context = this; 

    this.autoValue; 
    this._productID = productID; 
    this._asyncRequestComplete = false; 


    this.hello = function() { 
     alert("hello world"); 
    } 

    this.constructor = (function() { 
     context.hello(); 
     context.autoValue = "testing: " + productID + "(" +  context._asyncRequestComplete + ")"; 
    })() 

}

Le résultat

var _asyncOrderLine = new AsyncOrderLine(1001); 

Alerte Montré: "Bonjour tout le monde"

_asyncOrderLine.autoValue = testing: 1001(false) 
_asyncOrderLine.constructor = 'undefined' 

Dans ce cas, je souhaite que le constructeur reste indéfini une fois l'objet créé.

Question

Y at-il une meilleure façon de le faire? Pourrait-il y avoir des effets secondaires imprévus en utilisant cette approche?

+2

D'une manière générale, ce que vous avez fait est très bien. Vous n'avez pas besoin d'exposer une propriété appelée constructeur du tout. Vous pouvez simplement exécuter la fonction dans AsyncOrderLine. Ensuite, vous pouvez éviter l'affectation de undefined à votre _instance.constructor. Cependant, la question est extrêmement large et difficile à répondre formellement. Il y a des moyens infinis pour accomplir ce que vous avez fait. – keparo

+1

"* Ce que j'ai fait était de créer une propriété et d'y assigner une méthode anonyme. *" - Pourquoi as-tu fait ça? –

+0

@ ŠimeVidas J'allais l'appeler autre chose qu'un constructeur et lui assigner une valeur. Je l'ai renommé pour la question. Le problème était que je voulais une fonction à exécuter lorsque j'ai créé l'objet. – dmck

Répondre

3

Il n'y a pas besoin de compliquer les choses comme ça. Vous pouvez exécuter le code que vous voulez dans votre constructeur:

function AsyncOrderLine(productID) { 

    this.autoValue; 
    this._productID = productID; 
    this._asyncRequestComplete = false; 

    this.hello = function() { 
     alert("hello world"); 
    } 

    // Run whatever arbitrary code you want...  
    this.hello(); 
    this.autoValue = "testing: " + productID + "(" + context._asyncRequestComplete + ")"; 
} 
2

Comme d'autres l'ont dit, il n'y a aucune raison pour que la propriété du constructeur. Vous pouvez simplement exécuter le code que vous voulez dans le corps de la fonction et il s'exécutera au moment où l'objet est initialisé. Si vous voulez exécuter du code asynchrone (comme les appels ajax), alors vous voudrez probablement passer une fonction d'achèvement dans le constructeur afin que le créateur de l'objet puisse savoir quand la partie asynchrone de l'initialisation de l'objet est complète car elle ne sera pas être complet lorsque l'objet revient de son initialisation. Cela ressemblerait à quelque chose comme ceci:

function function AsyncOrderLine(productID, fn) { 
    // initialization code for the object here 
    this._asyncRequestComplete = false; 
    ... 

    // kick of asychronous networking call here 
    var context = this; 
    $.getJSON(url, function(data) { 
     // process the data response into our object here 
     context.whatever = data; 

     context._asyncRequestComplete = true; 
     // call the completion function with `this` set to point to our object here 
     // so the creator of this object can know when the async part of 
     // initialization is actually done 
     fn.call(context); 
    }); 
} 

Et puis un appelant ferait quelque chose comme ceci:

var x = new AsyncOrderLine(id, function() { 
    // can reference new object and it's methods and properties via "this" 
    alert("orderLine object is now completely initialized"); 
});