407 votes

Les constructeurs en objets JavaScript

Peut-classes JavaScript/objets possèdent des constructeurs? Comment sont-ils créés?

410voto

Nick Points 4572

À l'aide de prototypes:

function Box(color) // Constructor
{
    this.color = color;
}

Box.prototype.getColor = function()
{
    return this.color;
}

Se cacher "de la couleur" (ressemble un peu à une variable membre privée):

function Box(col)
{
   var color = col;

   this.getColor = function()
   {
       return color;
   }
}

Utilisation:

var blueBox = new Box("blue");
alert(blueBox.getColor()); // will alert blue

var greenBox = new Box("green");
alert(greenBox.getColor()); // will alert green

247voto

Blixt Points 23266

Voici un modèle que j'ai parfois l'utilisation de la programmation orientée objet-un comportement similaire en JavaScript. Comme vous pouvez le voir, vous pouvez simuler privé (en statique et en instance) les membres à l'aide de fermetures. Ce new MyClass() sera de retour est un objet avec les propriétés attribuées à l' this objet et dans l' prototype objet de la "classe".

var MyClass = (function () {
    // private static
    var nextId = 1;

    // constructor
    var cls = function () {
        // private
        var id = nextId++;
        var name = 'Unknown';

        // public (this instance only)
        this.get_id = function () { return id; };

        this.get_name = function () { return name; };
        this.set_name = function (value) {
            if (typeof value != 'string')
                throw 'Name must be a string';
            if (value.length < 2 || value.length > 20)
                throw 'Name must be 2-20 characters long.';
            name = value;
        };
    };

    // public static
    cls.get_nextId = function () {
        return nextId;
    };

    // public (shared across instances)
    cls.prototype = {
        announce: function () {
            alert('Hi there! My id is ' + this.get_id() + ' and my name is "' + this.get_name() + '"!\r\n' +
                  'The next fellow\'s id will be ' + MyClass.get_nextId() + '!');
        }
    };

    return cls;
})();

J'ai demandé à propos de l'héritage à l'aide de ce modèle, donc voilà:

// It's a good idea to have a utility class to wire up inheritance.
function inherit(cls, superCls) {
    // We use an intermediary empty constructor to create an
    // inheritance chain, because using the super class' constructor
    // might have side effects.
    var construct = function () {};
    construct.prototype = superCls.prototype;
    cls.prototype = new construct;
    cls.prototype.constructor = cls;
    cls.super = superCls;
}

var MyChildClass = (function () {
    // constructor
    var cls = function (surName) {
        // Call super constructor on this instance (any arguments
        // to the constructor would go after "this" in call(…)).
        this.constructor.super.call(this);

        // Shadowing instance properties is a little bit less
        // intuitive, but can be done:
        var getName = this.get_name;

        // public (this instance only)
        this.get_name = function () {
            return getName.call(this) + ' ' + surName;
        };
    };
    inherit(cls, MyClass); // <-- important!

    return cls;
})();

Et un exemple à ça:

var bob = new MyClass();
bob.set_name('Bob');
bob.announce(); // id is 1, name shows as "Bob"

var john = new MyChildClass('Doe');
john.set_name('John');
john.announce(); // id is 2, name shows as "John Doe"

alert(john instanceof MyClass); // true

Comme vous pouvez le voir, les classes correctement interagir les uns avec les autres (ils partagent la statique id d' MyClass, announce méthode utilise le bon get_name méthode, etc.)

Une chose à noter est la nécessité de l'ombre des propriétés d'une instance. Vous pouvez réellement faire de l' inherit de la fonction aller à travers toutes les propriétés de l'occurrence (à l'aide d' hasOwnProperty) qui sont des fonctions, et d'automatiquement ajouter un super_<method name> de la propriété. Ce serait vous appelez this.super_get_name() , au lieu de les stocker dans une valeur temporaire et l'appel lié à l'aide de call.

Pour les méthodes sur le prototype que vous n'avez pas besoin de s'inquiéter à ce sujet, cependant, si vous souhaitez accéder à la super-classe de " prototype méthodes, vous pouvez les appeler this.constructor.super.prototype.methodName. Si vous voulez la rendre moins verbeux vous pouvez bien sûr ajouter la commodité des propriétés. :)

166voto

Jon Points 1176

Il me semble que la plupart de vous donner l'exemple de getters et setters pas un constructeur, c'est à dire http://en.wikipedia.org/wiki/Constructor_(objet oriented_programming).

déjeuné-dan était plus proche, mais l'exemple ne fonctionne pas dans jsFiddle.

Cet exemple crée un constructeur privé de la fonction qui ne fonctionne que lors de la création de l'objet.

var color = 'black';

function Box()
{
   // private property
   var color = '';

   // private constructor 
   var __construct = function() {
       alert("Object Created.");
       color = 'green';
   }()

   // getter
   this.getColor = function() {
       return color;
   }

   // setter
   this.setColor = function(data) {
       color = data;
   }

}

var b = new Box();

alert(b.getColor()); // should be green

b.setColor('orange');

alert(b.getColor()); // should be orange

alert(color); // should be black

Si vous voulais attribuer des propriétés publiques, alors que le constructeur pourrait être défini comme tel:

var color = 'black';

function Box()
{
   // public property
   this.color = '';

   // private constructor 
   var __construct = function(that) {
       alert("Object Created.");
       that.color = 'green';
   }(this)

   // getter
   this.getColor = function() {
       return this.color;
   }

   // setter
   this.setColor = function(color) {
       this.color = color;
   }

}

var b = new Box();

alert(b.getColor()); // should be green

b.setColor('orange'); 

alert(b.getColor()); // should be orange

alert(color); // should be black

23voto

Joost Diepenmaat Points 171

Quel est donc le point de "constructeur" propriété? Ne peut pas comprendre d'où il etre utile, des idées?

Le point de la propriété constructeur est de fournir un moyen de faire semblant de JavaScript a des classes. Une des choses que vous ne peut utilement faire est de changer un constructeur de l'objet après qu'il a été créé. C'est compliqué.

J'ai écrit un assez complet sur elle il y a quelques années: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html

16voto

bitlather Points 187

Exemple ici: http://jsfiddle.net/FZ5nC/

Essayez ce modèle:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Name = Name||{};
Name.Space = Name.Space||{};

//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Name.Space.ClassName = function Name_Space_ClassName(){}

//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Name.Space.ClassName.prototype = {
  v1: null
 ,v2: null
 ,f1: function Name_Space_ClassName_f1(){}
}

//============================================================
// Static Variables
//------------------------------------------------------------
Name.Space.ClassName.staticVar = 0;

//============================================================
// Static Functions
//------------------------------------------------------------
Name.Space.ClassName.staticFunc = function Name_Space_ClassName_staticFunc(){
}
</script>

Vous devez ajuster votre espace de noms si vous êtes à la définition d'une classe statique:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};
Shape.Rectangle = Shape.Rectangle||{};
// In previous example, Rectangle was defined in the constructor.
</script>

Exemple de classe:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Shape = Shape||{};

//============================================================
// Constructor - MUST BE AT TOP OF FILE
//------------------------------------------------------------
Shape.Rectangle = function Shape_Rectangle(width, height, color){
    this.Width = width;
    this.Height = height;
    this.Color = color;
}

//============================================================
// Member Functions & Variables
//------------------------------------------------------------
Shape.Rectangle.prototype = {
  Width: null
 ,Height: null
 ,Color: null
 ,Draw: function Shape_Rectangle_Draw(canvasId, x, y){
    var canvas = document.getElementById(canvasId);
    var context = canvas.getContext("2d");
    context.fillStyle = this.Color;
    context.fillRect(x, y, this.Width, this.Height);
 }
}

//============================================================
// Static Variables
//------------------------------------------------------------
Shape.Rectangle.Sides = 4;

//============================================================
// Static Functions
//------------------------------------------------------------
Shape.Rectangle.CreateSmallBlue = function Shape_Rectangle_CreateSmallBlue(){
    return new Shape.Rectangle(5,8,'#0000ff');
}
Shape.Rectangle.CreateBigRed = function Shape_Rectangle_CreateBigRed(){
    return new Shape.Rectangle(50,25,'#ff0000');
}
</script>

Exemple d'instanciation:

<canvas id="painting" width="500" height="500"></canvas>
<script>
alert("A rectangle has "+Shape.Rectangle.Sides+" sides.");

var r1 = new Shape.Rectangle(16, 12, "#aa22cc");
r1.Draw("painting",0, 20);

var r2 = Shape.Rectangle.CreateSmallBlue();
r2.Draw("painting", 0, 0);

Shape.Rectangle.CreateBigRed().Draw("painting", 10, 0);
</script>

Avis de fonctions sont définies comme A. B = fonction A_B(). C'est pour rendre votre script plus facile à déboguer. Ouvrez google Chrome, Inspecter l'Élément du panneau, l'exécution de ce script, et d'élargir la trace de débogage:

<script>
//============================================================
// Register Namespace
//------------------------------------------------------------
var Fail = Fail||{};

//============================================================
// Static Functions
//------------------------------------------------------------
Fail.Test = function Fail_Test(){
    A.Func.That.Does.Not.Exist();
}

Fail.Test();
</script>

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X