Konstruktoren in JavaScript-Objekten

Antworten:

408

Prototypen verwenden:

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

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

"Farbe" ausblenden (ähnelt etwas einer privaten Mitgliedsvariablen):

function Box(col)
{
   var color = col;

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

Verwendungszweck:

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

var greenBox = new Box("green");
alert(greenBox.getColor()); // will alert green
Nick
quelle
3
@BorisB, ja, das tun Sie - dies definiert Farbe und getColor für das Box-Objekt, andernfalls weisen Sie Variablen im üblichen Bereich zu.
Nick
4
@Jeach ja das tut es. Ich habe ein alternatives Snippet bereitgestellt, das sich versteckt color. Ich würde vorschlagen, welche Sie verwenden, hängt weitgehend von
Nick
6
@CamiloMartin Obwohl dies nicht immer erforderlich ist, kann es nützlich sein, eine Variable "privat" (oder in diesem Fall unbenennbar) zu machen, um zu verhindern, dass externer Code von den Implementierungsdetails Ihrer Klasse abhängig wird. Selbst die Angabe, welche Elemente der Klasse öffentlich / privat sind, kann für externe Benutzer nützlich sein.
Nick
49
varmacht eine private Variable. thismacht eine öffentliche Variable
EhevuTov
3
@AlanKis (zumindest in einigen Javascript-Engines) wird der Stack-Trace im anonymen Funktionsfall nicht einmal erwähnt Foo, während er im letzteren Fall weiß, dass Fooer aufgerufen wird. Sehr hilfreich beim Debuggen.
Joachim Isaksson
248

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 mithilfe von Closures simulieren. Was zurückgegeben new MyClass()wird, ist ein Objekt mit nur den Eigenschaften, die dem thisObjekt und im prototypeObjekt der "Klasse" zugewiesen sind .

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 anhand dieses Musters gefragt.

// 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 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 die statische ID von MyClass, die announceMethode verwendet die richtige get_nameMethode usw.)

Eine Sache zu beachten ist die Notwendigkeit, Instanzeigenschaften zu beschatten. Sie können die inheritFunktion tatsächlich alle Instanzeigenschaften (mit hasOwnProperty) durchlaufen lassen, die Funktionen sind, und automatisch eine super_<method name>Eigenschaft hinzufügen . Auf diese Weise können Sie aufrufen, this.super_get_name()anstatt es in einem temporären Wert zu speichern und es gebunden mit aufzurufen call.

Bei Methoden für den Prototyp müssen Sie sich jedoch nicht um die oben genannten Punkte kümmern. Wenn Sie auf die Prototypmethoden der Superklasse zugreifen möchten, können Sie einfach aufrufen this.constructor.super.prototype.methodName. Wenn Sie es weniger ausführlich gestalten möchten, können Sie natürlich praktische Eigenschaften hinzufügen. :) :)

Blixt
quelle
7
Nur ein Hinweis zu dem cls.prototypeTeil: "Instanzenübergreifend geteilt" dient nur zum Lesen des Werts (Aufruf announce). Wenn Sie einen myClassInstance.announceanderen Wert festlegen , wird eine neue Eigenschaft in erstellt myClassInstance, sodass dies nur für dieses Objekt gilt, nicht für andere Instanzen der Klasse. Das Zuweisen zu wirkt sich MyClass.prototype.announcejedoch auf alle Instanzen aus.
Matthew Crumley
1
Kein Problem, ich bin froh, Ihnen helfen zu können! :)
Blixt
2
Vielen Dank! Sehr gut gefallen! Könnten Sie ein Beispiel für die Klassenvererbung in diesem Ansatz zeigen?
Dmitrij Golubev
2
@DmitrijGolubev, Brad Dwyer und Nathan C. Tresch: Ich habe Vererbung hinzugefügt, aber es wird ziemlich kompliziert, daher würde ich Ihnen normalerweise raten, eine einfachere Lösung zu wählen, es sei denn, Sie benötigen eine solche Hardcore-Vererbung in JavaScript (was eigentlich nur eine ist prototypische Sprache).
Blixt
1
@guiomie Es ist eine "öffentliche statische" Methode, also würden Sie sie für die Konstruktorfunktion (die "Klasse") aufrufen, nicht für die Instanz:MyClass.get_nextId()
Blixt
166

Es scheint mir, dass die meisten von Ihnen ein Beispiel für Getter und Setter geben, die kein Konstruktor sind (dh http://en.wikipedia.org/wiki/Constructor_(object-oriented_programming) .

Mittagessen-Dan war näher, aber das Beispiel funktionierte nicht in jsFiddle.

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 möchten, kann der Konstruktor wie folgt 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
Jon
quelle
45
Wie ist das nicht die Antwort Nr. 1? Nur Jon hat einen Konstruktor mit Parametern erstellt.
Rap
1
Gibt es eine Möglichkeit, mit diesem Paradigma für Konstruktoren ein Beispiel für die Vererbung zu erhalten?
Nathan C. Tresch
1
@Rap Jons Konstruktorbeispiel hat keine Parameter, da es sich um eine Box()Funktion handelt :). Dieses Beispiel sowie Beispiele in den anderen Antworten können jedoch leicht erweitert werden, um Parameter zu akzeptieren.
Alexander Stepaniuk
2
@AndersonGreen Sie können Box einen Parameter hinzufügen und ihn dann als Funktionsparameter an den privaten Konstruktor übergeben.
Gautham C.
1
Es besteht keine Notwendigkeit für "private Konstrukteure". Machen Sie einfach Ihre Konstruktion in der BoxFunktion und Sie können loslegen (es ist immer noch "privat"). "Privat" in Javascript bedeutet nur, über den lexikalischen Bereich zugänglich zu sein. Keine Notwendigkeit, Mitgliedern zuzuweisen. Zusätzlich: Dieser Code ist falsch. Es wird eine globale __constructVariable erstellt, was ziemlich schlecht ist. varsollte verwendet werden, um den Umfang von einzuschränken __construct.
Mattbasta
23

Was ist der Sinn der "Konstruktor" -Eigenschaft? Sie können nicht herausfinden, wo es nützlich sein könnte, irgendwelche Ideen?

Der Zweck der Konstruktoreigenschaft besteht darin, eine Möglichkeit bereitzustellen, so zu tun, als ob JavaScript Klassen hat. Sie können den Konstruktor eines Objekts nach seiner Erstellung nicht sinnvoll ändern. Es ist kompliziert.

Ich habe vor einigen Jahren ein ziemlich umfassendes Stück darüber geschrieben: http://joost.zeekat.nl/constructors-considered-mildly-confusing.html

Joost Diepenmaat
quelle
Es geht darum, das Schlüsselwort "new" zu verwenden. "d = new Drofto ()" erstellt ein leeres Objekt und führt die Drofto-Funktion aus, wobei das neue Objekt als "this" begrenzt ist. Die Drofto-Funktion kann alles zurückgeben, es ist jedoch üblich, etwas zurückzugeben, das als Mitglied der Drofto-Klasse angesehen werden soll.
Juan Lanus
16

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

Beispielklasse:

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

Beispielinstanziierung:

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

Hinweisfunktionen sind definiert als AB = Funktion A_B (). Dies soll das Debuggen Ihres Skripts erleichtern. Öffnen Sie das Inspect Element-Bedienfeld von Chrome, führen Sie dieses 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>
Bitlather
quelle
Beispiel hinzugefügt. Außerdem wurden Informationen zur Verbesserung der Debug-Ausgabe hinzugefügt.
Bitlather
1
Wahrscheinlich, weil das Problem dadurch unnötig komplex wird. Aufgrund des pedantischen Namensabstands und der statischen Klassendeklaration ist es schwierig, die Antwort in Ihrem Beitrag zu finden. Versteh mich nicht falsch, es sind gute Informationen, aber es ist sicherlich eher verwirrend als hilfreich, wenn Sie versuchen, beim Verstehen einen Fuß in die Tür zu bekommen. Ich bin halbwegs kompetent in JS und verstehe kaum, was Sie hier tun oder warum es für "Wie konstruiere ich?" Relevant ist.
Bmo
1
Danke für den Einblick, Bmo. Es war ein langer Beitrag, aber ich verstehe die Verwendung eines Konstruktors nicht, wenn er nicht an ein genau definiertes Objekt und eine statische Klassenimplementierung gebunden ist. Wenn Sie C ++ oder Java lernen, müssen Sie lernen, wie Sie Klassen implementieren und wie Sie Konstruktoren implementieren. Web-Entwickler haben viel mehr Spaß gemacht, seit ich auf diese Methode des Schreibens von Javascript gestoßen bin, und ich wollte sie nur teilen. Ich habe die Geige nach oben bewegt, damit sie leichter zu finden ist. Ich hoffe, das wird jede Verwirrung klären.
Bitlather
1
@Bmo Ist es Ihnen ernst, dass die beiden Zeilen über den Namespace es schwierig machen, den Konstruktor genau unten zu finden, insbesondere angesichts des Kommentars Konstruktor - MUSS OBEN IN DER DATEI SEIN? Das Bereitstellen eines Beispiels mit einem Namespace ist sehr willkommen. Die Javascript-Entwicklergemeinschaft ignoriert blind Namespaces, was zu schwer zu findenden Fehlern führt, wenn Namen aufeinander treffen. Es ist traurig zu sehen, dass js Entwickler denken, wenn sie einen Text aus einem Beitrag im Internet kopieren und etwas Ähnliches tun, was sie brauchen, ist ihre Arbeit abgeschlossen.
user3285954
1
Das Hauptproblem bei js und der Webentwicklung im Allgemeinen ist, dass die meisten Entwickler alle Praktiken ignorieren, die die Branche in mehr als 50 Jahren entwickelt hat, und denken, wenn sie einen Ajax-Anruf tätigen können, sind sie der König. Es ist so traurig zu sehen, dass es so viele Jahre gedauert hat, bekannte Muster und Praktiken in Javascript zu verwenden.
user3285954
10

Dies ist ein Konstruktor:

function MyClass() {}

Wenn Sie das tun

var myObj = new MyClass();

MyClass wird ausgeführt und ein neues Objekt dieser Klasse zurückgegeben.

Satish N Ramteare
quelle
1
Um zu verdeutlichen, was dies bedeutet, können Sie sagen alert(valuePassedInAsArgument);, dass dies ganz oben in Ihrer Klasse steht. Dies wird für jede Instanziierung einmal ausgeführt, sodass die gesamte Klasse der Konstruktor selbst ist.
Martin Lyne
new object is returned of that class- Ist es nicht eher so, als würde ein neues Objekt dieser Funktion zurückgegeben?
Don Cheadle
in Javascript Funktionen sind Objekte
Leo
8

Ich fand dieses Tutorial sehr nützlich. Dieser Ansatz wird von den meisten jQuery-Plug-Ins verwendet.

http://www.htmlgoodies.com/html5/tutorials/create-an-object-oriented-javascript-class-constructor.html#fbid=OVYAQL_TDpK

var Class = function(methods) {   
    var klass = function() {    
        this.initialize.apply(this, arguments);          
    };  

    for (var property in methods) { 
       klass.prototype[property] = methods[property];
    }

    if (!klass.prototype.initialize) klass.prototype.initialize = function(){};      

    return klass;    
};

Jetzt ,

var Person = Class({ 
    initialize: function(name, age) {
        this.name = name;
        this.age  = age;
    },
    toString: function() {
        return "My name is "+this.name+" and I am "+this.age+" years old.";
    }
}); 

var alice = new Person('Alice', 26);
alert(alice.name); //displays "Alice"
alert(alice.age); //displays "26"
alert(alice.toString()); //displays "My name is Alice and I am 26 years old" in most browsers.
//IE 8 and below display the Object's toString() instead! "[Object object]"
Anasanjaria
quelle
10
Ich erschrecke, wenn ich Leute sehe, dieklass
Madbreaks
8

Dieses Muster hat mir gut gedient. Mit diesem Muster erstellen Sie Klassen in separaten Dateien und laden sie "nach Bedarf" in Ihre gesamte App.

// Namespace
// (Creating new if not instantiated yet, otherwise, use existing and just add to it)
var myApp = myApp || {};

// "Package" 
// Similar to how you would establish a package in other languages
(function() {

// "Class"
var MyClass = function(params) {
    this.initialize(params);
}

    // "Private Static" vars 
    //    - Only accessible to functions in this class.
    //    - Doesn't get wiped out when we create a new instance.
    var countInstances = 0;
    var allInstances = [];

    // "Private Static" functions 
    //    - Same as above, but it's a function accessible 
    //      only to other functions in this class.
    function doSomething(){
    }

    // "Public Static" vars
    //    - Everyone has access.
    //    - Doesn't get wiped out when we create a new instance.
    MyClass.counter = 0;

    // "Public Static" functions
    //    - Same as above, but anyone can call this "static method".
    //    - Kinda like a singleton class situation.
    MyClass.foobar = function(){
    }

    // Public properties and methods are built into the "prototype"
    //    - This is how each instance can become unique unto itself.
    //    - Establishing "p" as "local" (Static Private) variable 
    //      simply so we don't have to keep typing "MyClass.prototype" 
    //      for each property and function.
var p = MyClass.prototype;

    // "Public" vars
    p.id = null;
    p.firstname = null;
    p.lastname = null;

    // "Private" vars
    //    - Only used by "this" instance.
    //    - There isn't "true" privacy for each 
    //      instance so we have to fake it. 
    //    - By tradition, we indicate "privacy"  
    //      by prefixing it with an underscore. 
    //    - So technically, anyone can access, but we simply 
    //      don't tell anyone about it (e.g. in your API)
    //      so no one knows about it :)
    p._foo = null;

    p.initialize = function(params){
        this.id = MyClass.counter++;
        this.firstname = params.firstname;
        this.lastname = params.lastname;
        MyClass.counter++;
        countInstances++;
        allInstances.push(this);
    }

    p.doAlert = function(theMessage){
        alert(this.firstname + " " + this.lastname + " said: " + theMessage + ". My id:" + this.id + ".  Total People:" + countInstances + ". First Person:" + allInstances[0].firstname + " " + allInstances[0].lastname);
    }


// Assign class to app
myApp.MyClass = MyClass;

// Close the "Package"
}());

// Usage example:
var bob = new myApp.MyClass({   firstname   :   "bob",
                                lastname    :   "er"
                            });

bob.doAlert("hello there");
Bob
quelle
Dies sind Instanzvariablen, aber sie sind "öffentlich" zugänglich, nicht "privat" wie in C ++ oder Java.
Potatoswatter
Wie würden Sie eine private Variable (im klassischen Sinne) erstellen, die relativ zur Instanz ist, aber nicht allen Instanzen gemeinsam ist?
Bob
Siehe Douglas Crockfords Website, er ist einer der Sprachdesigner und eine der wichtigsten Autoritäten. Ich folge nicht immer seinen Mustern, aber im Allgemeinen ist eine private Variable eine lokale Variable varim Konstruktor (oder Funktionsargument oder in einer konstruktorähnlichen Funktion).
Potatoswatter
Vielen Dank für den Tipp ... die folgende Seite erklärt, wonach ich gesucht habe: javascript.crockford.com/private.html
Bob
Oh, tut mir leid, dass
ich
8

Ja, Sie können einen Konstruktor in einer Klassendeklaration wie folgt definieren:

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}
Bruno
quelle
für vaersion IE> 12
zloctb
1
Dies ist die einzige tatsächliche Antwort auf die Frage. : /
MarcD
6

Ich werde wohl posten, was ich mit dem Schließen von Javascript mache, da noch niemand das Schließen verwendet.

var user = function(id) {
  // private properties & methods goes here.
  var someValue;
  function doSomething(data) {
    someValue = data;
  };

  // constructor goes here.
  if (!id) return null;

  // public properties & methods goes here.
  return {
    id: id,
    method: function(params) {
      doSomething(params);
    }
  };
};

Kommentare und Vorschläge zu dieser Lösung sind willkommen. :) :)

Hendra Uzia
quelle
1
Ein paar Kommentare: 1) Wenn (! Id) nicht sicher ist, führen Werte wie 0 oder false dazu, dass true ausgewertet wird und null zurückgegeben wird. Ich vermute, Sie möchten nach undefiniert oder null suchen. In diesem Fall wäre === null und === undefiniert besser. 2) Dies ähnelt eher dem Modulmuster ( adäquatgood.com/2010 / 3/JavaScript-Module-Pattern-In- Depth ) als einem Konstruktor, wobei der Unterschied darin besteht, dass ein Modul ein Objekt aus der Funktion zurückgibt, während ein Konstruktor ein Objekt erstellt, wenn gepaart mit dem neuen Schlüsselwort. In diesem Fall würden Sie anstelle eines Objekts Werte für 'this' festlegen.
Rich
4

Mit dem obigen Beispiel von Nick können Sie einen Konstruktor für Objekte ohne Parameter erstellen, indem Sie eine return-Anweisung als letzte Anweisung in Ihrer Objektdefinition verwenden. Geben Sie Ihre Konstruktorfunktion wie folgt zurück, und der Code wird bei jeder Erstellung des Objekts in __construct ausgeführt:

function Box()
{
   var __construct = function() {
       alert("Object Created.");
       this.color = 'green';
   }

  this.color = '';

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

   __construct();
}

var b = new Box();
Dan Power
quelle
1
Sie geben die Konstruktorfunktion nicht zurück, sondern rufen sie nur auf.
David Conrad
Wenn Sie versuchen, this.getColor();in der obigen Zeile zu verwenden, wird alert("Object Created.");nichts alarmiert. Es wird ein Fehler wie "getColor ist nicht definiert" angezeigt. Wenn Sie möchten, dass das Konstrukt andere Methoden im Objekt aufrufen kann, muss es nach allen anderen Methoden definiert werden. Anstatt also __construct();die letzte Zeile aufzurufen, definieren Sie einfach das Konstrukt dort unten und setzen ()Sie es nach, um die automatische Ausführung zu erzwingen.
Thinsoldier
Korrektur. Das Hinzufügen ()am Ende der __construct-Definition führte immer noch zu dem Fehler. Ich musste __construct();wie im Originalcode in einer eigenen Leitung anrufen , um den Fehler zu vermeiden.
Thinsoldier
4

Vielleicht ist es etwas einfacher geworden, aber im Folgenden habe ich mir 2017 Folgendes ausgedacht:

class obj {
  constructor(in_shape, in_color){
    this.shape = in_shape;
    this.color = in_color;
  }

  getInfo(){
    return this.shape + ' and ' + this.color;
  }
  setShape(in_shape){
    this.shape = in_shape;
  }
  setColor(in_color){
    this.color = in_color;
  }
}

Bei Verwendung der obigen Klasse habe ich Folgendes:

var newobj = new obj('square', 'blue');

//Here, we expect to see 'square and blue'
console.log(newobj.getInfo()); 

newobj.setColor('white');
newobj.setShape('sphere');

//Since we've set new color and shape, we expect the following: 'sphere and white'
console.log(newobj.getInfo());

Wie Sie sehen können, akzeptiert der Konstruktor zwei Parameter, und wir legen die Eigenschaften des Objekts fest. Wir ändern auch die Farbe und Form des Objekts mithilfe der setterFunktionen und beweisen, dass seine Änderung beim Aufruf getInfo()nach diesen Änderungen erhalten blieb.

Ein bisschen spät, aber ich hoffe das hilft. Ich habe dies mit einem mochaUnit-Test getestet und es funktioniert gut.

Chim Chimz
quelle
3

Sie tun dies, wenn Sie Typescript verwenden - Open Source von MicroSoft :-)

class BankAccount {
 balance: number;
 constructor(initially: number) {
 this.balance = initially;
 }
 deposit(credit: number) {
 this.balance += credit;
 return this.balance;
 }
}

Mit Typescript können Sie OO-Konstrukte "fälschen", die zu Javascript-Konstrukten kompiliert werden. Wenn Sie ein großes Projekt starten, sparen Sie möglicherweise viel Zeit und haben gerade die Version 1.0 erreicht.

http://www.typescriptlang.org/Content/TypeScript%20Language%20Specification.pdf

Der obige Code wird kompiliert zu:

var BankAccount = (function () {
    function BankAccount(initially) {
        this.balance = initially;
    }
    BankAccount.prototype.deposit = function (credit) {
        this.balance += credit;
        return this.balance;
    };
    return BankAccount;
})();
Simon_Weaver
quelle
Ich arbeite an einem großen Projekt und versuche die Leute davon zu überzeugen, dass TypeScript uns ein laufendes Shooting geben wird. Wir werden sehen, wie das geht.
Wootscootinboogie
@wootscootinboogie An einem Tag (der jetzt um 5.30 Uhr endet) bin ich ziemlich weit gekommen und habe mich ziemlich wohl damit gefühlt. Ich empfehle dringend, die Spezifikation durchzulesen, und obwohl Sie die Hälfte der wirklich kniffligen Dinge überspringen können, tun Sie sich selbst einen Gefallen, wenn Sie sie mindestens einmal durchlesen. Die Videos dieses Typen sind ausgezeichnet. youtube.com/user/basaratali/videos .
Viel
1

In JavaScript definiert der Aufruftyp das Verhalten der Funktion:

  • Direkter Aufruf func()
  • Methodenaufruf für ein Objekt obj.func()
  • constructor - Aufrufnew func()
  • Indirekter Aufruf func.call()oderfunc.apply()

Die Funktion wird beim Aufruf mit dem Operator als Konstruktor aufgerufen new:

function Cat(name) {
   this.name = name;
}
Cat.prototype.getName = function() {
   return this.name;
}

var myCat = new Cat('Sweet'); // Cat function invoked as a constructor

Jede Instanz oder jedes Prototypobjekt in JavaScript verfügt über eine Eigenschaft constructor, die auf die Konstruktorfunktion verweist.

Cat.prototype.constructor === Cat // => true
myCat.constructor         === Cat // => true

Überprüfen Sie diesen Beitrag über die Konstruktoreigenschaft.

Dmitri Pavlutin
quelle
0

Während ich die großartige Vorlage von Blixt von oben verwendete, stellte ich fest, dass sie mit der mehrstufigen Vererbung (MyGrandChildClass, die MyChildClass erweitert, um MyClass zu erweitern) nicht gut funktioniert. Der Aufruf des Konstruktors des ersten Elternteils erfolgt immer wieder. Hier ist eine einfache Problemumgehung: Wenn Sie eine mehrstufige Vererbung benötigen, anstatt die this.constructor.super.call(this, surName);Verwendung chainSuper(this).call(this, surName);mit der wie folgt definierten Kettenfunktion zu verwenden:

function chainSuper(cls) {
  if (cls.__depth == undefined) cls.__depth = 1; else cls.__depth++;
  var depth = cls.__depth;
  var sup = cls.constructor.super;
  while (depth > 1) {
    if (sup.super != undefined) sup = sup.super;
    depth--;
  }
  return sup;
}
jan
quelle
0

http://www.jsoops.net/ ist ziemlich gut für oop in Js. Wenn Sie private, geschützte, öffentliche Variablen und Funktionen sowie Vererbungsfunktionen bereitstellen. Beispielcode:

var ClassA = JsOops(function (pri, pro, pub)
{// pri = private, pro = protected, pub = public

    pri.className = "I am A ";

    this.init = function (var1)// constructor
    {
        pri.className += var1;
    }

    pub.getData = function ()
    {
        return "ClassA(Top=" + pro.getClassName() + ", This=" + pri.getClassName()
        + ", ID=" + pro.getClassId() + ")";
    }

    pri.getClassName = function () { return pri.className; }
    pro.getClassName = function () { return pri.className; }
    pro.getClassId = function () { return 1; }
});

var newA = new ClassA("Class");

//***Access public function
console.log(typeof (newA.getData));
// function
console.log(newA.getData());
// ClassA(Top=I am A Class, This=I am A Class, ID=1)

//***You can not access constructor, private and protected function
console.log(typeof (newA.init));            // undefined
console.log(typeof (newA.className));       // undefined
console.log(typeof (newA.pro));             // undefined
console.log(typeof (newA.getClassName));    // undefined
user1624059
quelle
0

nur um etwas Abwechslung zu bieten. ds.oop ist eine gute Möglichkeit, Klassen mit Konstruktoren in Javascript zu deklarieren. Es unterstützt jede mögliche Art der Vererbung (einschließlich eines Typs, den selbst c # nicht unterstützt) sowie Schnittstellen, was sehr hilfreich ist.

var Color = ds.make.class({
    type: 'Color',
    constructor: function (r,g,b) { 
        this.r = r;                     /* now r,g, and b are available to   */
        this.g = g;                     /* other methods in the Color class  */
        this.b = b;                     
    }
});
var red = new Color(255,0,0);   // using the new keyword to instantiate the class
dss
quelle
0

Hier müssen wir einen Punkt im Java-Skript beachten, es ist eine klassenlose Sprache, aber wir können es erreichen, indem wir Funktionen im Java-Skript verwenden. Der häufigste Weg, um dies zu erreichen, besteht darin, eine Funktion im Java-Skript zu erstellen und ein neues Schlüsselwort zum Erstellen eines Objekts zu verwenden und dieses Schlüsselwort zum Definieren von Eigenschaften und Methoden zu verwenden. Unten sehen Sie das Beispiel.

// Function constructor

   var calculator=function(num1 ,num2){
   this.name="This is function constructor";
   this.mulFunc=function(){
      return num1*num2
   };

};

var objCal=new calculator(10,10);// This is a constructor in java script
alert(objCal.mulFunc());// method call
alert(objCal.name);// property call

//Constructors With Prototypes

var calculator=function(){
   this.name="Constructors With Prototypes";
};

calculator.prototype.mulFunc=function(num1 ,num2){
 return num1*num2;
};
var objCal=new calculator();// This is a constructor in java script
alert(objCal.mulFunc(10,10));// method call
alert(objCal.name); // property call
Sheo Dayal Singh
quelle
-2

In den meisten Fällen müssen Sie die benötigte Eigenschaft irgendwie deklarieren, bevor Sie eine Methode aufrufen können, die diese Informationen übergibt. Wenn Sie zunächst keine Eigenschaft festlegen müssen, können Sie einfach eine Methode innerhalb des Objekts wie folgt aufrufen. Wahrscheinlich nicht die schönste Art, dies zu tun, aber das funktioniert immer noch.

var objectA = {
    color: ''; 
    callColor : function(){
        console.log(this.color);
    }
    this.callColor(); 
}
var newObject = new objectA(); 
Codierter Container
quelle