407 Stimmen

Konstrukteure in JavaScript-Objekten

Können JavaScript-Klassen/Objekte Konstruktoren haben? Wie werden sie erstellt?

410voto

Nick Punkte 7560

Verwendung von Prototypen:

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

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

Ausblenden von "Farbe" (ähnelt einer privaten Mitgliedsvariablen):

function Box(col)
{
   var color = col;

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

Verwendung:

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

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

247voto

Blixt Punkte 48333

Hier ist eine Vorlage, die ich manchmal für OOP-ähnliches Verhalten in JavaScript verwende. Wie Sie sehen können, können Sie private (sowohl statische als auch Instanz-) Mitglieder mit Closures simulieren. Was new MyClass() wird ein Objekt zurückgegeben, das nur die Eigenschaften enthält, die dem this Objekt und in der prototype Objekt der "Klasse".

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;
})();

Ich wurde nach der Vererbung nach diesem Muster gefragt, also hier ist sie:

// 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;
})();

Und ein Beispiel, um das alles zu nutzen:

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

Wie Sie sehen können, interagieren die Klassen korrekt miteinander (sie teilen sich die statische ID von MyClass die announce Methode verwendet die korrekte get_name Methode, usw.)

Zu beachten ist die Notwendigkeit, Instanzeigenschaften zu beschatten. Sie können tatsächlich die inherit Funktion alle Instanzeigenschaften durchlaufen (mit hasOwnProperty ), die Funktionen sind, und fügen automatisch ein super_<method name> Eigentum. Damit können Sie Folgendes aufrufen this.super_get_name() anstatt ihn in einem temporären Wert zu speichern und ihn gebunden aufzurufen, indem man call .

Für die Methoden des Prototyps müssen Sie sich jedoch keine Gedanken machen, wenn Sie auf die Methoden des Prototyps der Superklasse zugreifen wollen, können Sie einfach this.constructor.super.prototype.methodName . Wenn Sie es weniger ausführlich machen wollen, können Sie natürlich Komfort-Eigenschaften hinzufügen :)

166voto

Jon Punkte 2196

Mir scheint, die meisten von Ihnen geben Beispiele für Getter und Setter und nicht für einen Konstruktor, d.h. http://en.wikipedia.org/wiki/Constructor_(objektorientierte_programmierung) .

lunched-dan war näher dran, aber das Beispiel hat in jsFiddle nicht funktioniert.

In diesem Beispiel wird eine private Konstruktorfunktion erstellt, die nur während der Erstellung des Objekts ausgeführt wird.

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

Wenn Sie öffentliche Eigenschaften zuweisen wollten, könnte der Konstruktor als solcher definiert werden:

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 Punkte 231

Was ist also der Sinn der Eigenschaft "Konstruktor"? Eigenschaft? Ich kann nicht herausfinden, wo sie nützlich sein könnte, irgendwelche Ideen?

Der Sinn der Konstruktor-Eigenschaft ist es, eine Möglichkeit zu bieten, JavaScript als Klassen auszugeben. Eines der Dinge, die Sie kann nicht sinnvollerweise den Konstruktor eines Objekts ändern, nachdem es erstellt worden ist. Das ist kompliziert.

Ich habe vor ein paar Jahren einen recht umfassenden Artikel darüber geschrieben: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html

16voto

bitlather Punkte 540

Beispiel hier: http://jsfiddle.net/FZ5nC/

Probieren Sie diese Vorlage aus:

<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>

Sie müssen Ihren Namensraum anpassen, wenn Sie eine statische Klasse definieren:

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

Beispiel Klasse:

<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>

Beispiel einer Instanziierung:

<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>

Beachten Sie, dass Funktionen als A.B = Funktion A_B() definiert sind. Dies soll die Fehlersuche in Ihrem Skript erleichtern. Öffnen Sie das Bedienfeld "Element inspizieren" von Chrome, führen Sie das Skript aus und erweitern Sie den Debug-Backtrace:

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

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

Fail.Test();
</script>

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X