Ich habe ein paar ähnliche Antworten gesehen, aber ich möchte diesen Beitrag erwähnen es am besten beschreibt, also möchte ich es mit Ihnen teilen.
Hier ist ein Code, den ich geändert habe, um ein vollständiges Beispiel zu erhalten, das hoffentlich der Community zugute kommt, da es als Entwurfsvorlage für Klassen verwendet werden kann.
Es beantwortet auch Ihre Frage:
function Podcast() {
// private variables
var _somePrivateVariable = 123;
// object properties (read/write)
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
// for read access to _somePrivateVariable via immutableProp
this.immutableProp = function() {
return _somePrivateVariable;
}
// object function
this.toString = function() {
return 'Title: ' + this.title;
}
};
// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
console.log('Downloading ' + podcast + ' ...');
};
In diesem Beispiel können Sie wie folgt auf die statischen Eigenschaften / Funktionen zugreifen :
// access static properties/functions
console.log(Podcast.FILE_EXTENSION); // 'mp3'
Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...'
Und die Objekteigenschaften / funktionieren einfach wie folgt:
// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString()); // Title: The Simpsons
console.log(podcast.immutableProp()); // 123
Beachten Sie, dass in podcast.immutableProp () ein Abschluss vorliegt : Der Verweis auf _somePrivateVariable bleibt in der Funktion erhalten.
Sie können sogar Getter und Setter definieren . Schauen Sie sich dieses Code-Snippet an (wo d
sich der Prototyp des Objekts befindet, für den Sie eine Eigenschaft deklarieren möchten, y
ist eine private Variable, die außerhalb des Konstruktors nicht sichtbar ist):
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {return this.getFullYear() },
set: function(y) { this.setFullYear(y) }
});
Es definiert die Eigenschaft d.year
über get
und set
Funktionen - wenn Sie nichts angeben set
, ist die Eigenschaft schreibgeschützt und kann nicht geändert werden (beachten Sie, dass Sie keine Fehlermeldung erhalten, wenn Sie versuchen, sie festzulegen , dies hat jedoch keine Auswirkungen). Jede Eigenschaft hat die Attribute writable
, configurable
(lassen Änderung nach Anmeldung) und enumerable
(lassen Sie es als Aufzählungs verwenden), die standardmäßig sind false
. Sie können sie über defineProperty
im 3. Parameter einstellen , z enumerable: true
.
Was auch gültig ist, ist diese Syntax:
// getters and setters - alternative syntax
var obj = { a: 7,
get b() {return this.a + 1;},
set c(x) {this.a = x / 2}
};
a
Dies definiert eine lesbare / beschreibbare Eigenschaft , eine schreibgeschützte Eigenschaft b
und eine schreibgeschützte Eigenschaft c
, über die auf die Eigenschaft a
zugegriffen werden kann.
Verwendungszweck:
console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21
Anmerkungen:
Um unerwartetes Verhalten zu vermeiden, falls Sie das new
Schlüsselwort vergessen haben , sollten Sie der Funktion Folgendes hinzufügen Podcast
:
// instantiation helper
function Podcast() {
if(false === (this instanceof Podcast)) {
return new Podcast();
}
// [... same as above ...]
};
Jetzt funktionieren beide der folgenden Instanziierungen wie erwartet:
var podcast = new Podcast(); // normal usage, still allowed
var podcast = Podcast(); // you can omit the new keyword because of the helper
Die 'neue' Anweisung erstellt ein neues Objekt und kopiert alle Eigenschaften und Methoden, d. H.
var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"
Beachten Sie auch, dass es in einigen Situationen nützlich sein kann, die return
Anweisung in der Konstruktorfunktion Podcast
zu verwenden, um benutzerdefinierte Objektschutzfunktionen zurückzugeben, auf die sich die Klasse intern stützt, die jedoch verfügbar gemacht werden müssen. Dies wird in Kapitel 2 (Objekte) der Artikelserie näher erläutert.
Das kann man sagen a
und b
erben von Podcast
. Was ist nun, wenn Sie Podcast eine Methode hinzufügen möchten, die für alle nach a
und b
nach der Instanziierung gilt? Verwenden Sie in diesem Fall .prototype
Folgendes:
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
Rufen Sie jetzt an a
und noch b
einmal:
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
Weitere Details zu Prototypen finden Sie hier . Wenn Sie mehr Vererbung vornehmen möchten, schlage ich vor, dies zu prüfen .
Es wird dringend empfohlen , die oben erwähnten Artikelserien zu lesen. Sie enthalten auch die folgenden Themen:
- Funktionen
- Objekte
- Prototypen
- Durchsetzen neuer Konstruktorfunktionen
- Heben
- Automatisches Einfügen von Semikolons
- Statische Eigenschaften und Methoden
Beachten Sie, dass das automatische Einfügen von Semikolons in JavaScript (wie in Abschnitt 6 erwähnt) sehr häufig für seltsame Probleme in Ihrem Code verantwortlich ist. Daher würde ich es eher als Fehler als als Feature betrachten.
Wenn Sie mehr lesen möchten, finden Sie hier einen interessanten MSDN-Artikel zu diesen Themen. Einige der dort beschriebenen Artikel enthalten noch mehr Details.
Was ist interessant zu lesen , wie gut (auch die Themen abdeckt wie oben erwähnt) sind die Artikel aus dem MDN JavaScript - Führer :
Wenn Sie wissen möchten, wie man c # out
-Parameter (wie in DateTime.TryParse(str, out result)
) in JavaScript emuliert , finden Sie hier Beispielcode.
Diejenigen unter Ihnen, die mit dem Internet Explorer arbeiten (der keine Konsole für JavaScript hat, es sei denn, Sie öffnen die Entwicklertools mit F12und öffnen die Registerkarte "Konsole"), finden das folgende Snippet möglicherweise hilfreich. Es ermöglicht Ihnen die Verwendung console.log(msg);
wie in den obigen Beispielen verwendet. Fügen Sie es einfach vor der Podcast
Funktion ein.
Hier ist der Code oben in einem vollständigen Code-Snippet:
let console = { log: function(msg) {
let canvas = document.getElementById("log"), br = canvas.innerHTML==="" ? "" : "<br/>";
canvas.innerHTML += (br + (msg || "").toString());
}};
console.log('For details, see the explaining text');
function Podcast() {
// with this, you can instantiate without new (see description in text)
if (false === (this instanceof Podcast)) {
return new Podcast();
}
// private variables
var _somePrivateVariable = 123;
// object properties
this.title = 'Astronomy Cast';
this.description = 'A fact-based journey through the galaxy.';
this.link = 'http://www.astronomycast.com';
this.immutableProp = function() {
return _somePrivateVariable;
}
// object function
this.toString = function() {
return 'Title: ' + this.title;
}
};
// static property
Podcast.FILE_EXTENSION = 'mp3';
// static function
Podcast.download = function(podcast) {
console.log('Downloading ' + podcast + ' ...');
};
// access static properties/functions
Podcast.FILE_EXTENSION; // 'mp3'
Podcast.download('Astronomy cast'); // 'Downloading Astronomy cast ...'
// access object properties/functions
var podcast = new Podcast();
podcast.title = 'The Simpsons';
console.log(podcast.toString()); // Title: The Simpsons
console.log(podcast.immutableProp()); // 123
// getters and setters
var d = Date.prototype;
Object.defineProperty(d, "year", {
get: function() {
return this.getFullYear()
},
set: function(y) {
this.setFullYear(y)
}
});
// getters and setters - alternative syntax
var obj = {
a: 7,
get b() {
return this.a + 1;
},
set c(x) {
this.a = x / 2
}
};
// usage:
console.log(obj.a); console.log(obj.b); // output: 7, 8
obj.c=40;
console.log(obj.a); console.log(obj.b); // output: 20, 21
var a=new Podcast();
var b=new Podcast();
a.title="a"; b.title="An "+b.title;
console.log(a.title); // "a"
console.log(b.title); // "An Astronomy Cast"
Podcast.prototype.titleAndLink = function() {
return this.title + " [" + this.link + "]";
};
console.log(a.titleAndLink()); // "a [http://www.astronomycast.com]"
console.log(b.titleAndLink()); // "An Astronomy Cast [http://www.astronomycast.com]"
<div id="log"></div>
Anmerkungen:
Einige gute Tipps, Hinweise und Empfehlungen zur JavaScript-Programmierung im Allgemeinen finden Sie hier (Best Practices für JavaScript) und dort ('var' versus 'let') . Empfehlenswert ist auch dieser Artikel über implizite Typografien (Zwang) .
Eine bequeme Möglichkeit, Klassen zu verwenden und sie in JavaScript zu kompilieren, ist TypeScript. Hier ist ein Spielplatz, auf dem Sie einige Beispiele finden, die Ihnen zeigen, wie es funktioniert. Auch wenn Sie momentan kein TypeScript verwenden, können Sie einen Blick darauf werfen, da Sie TypeScript nebeneinander mit dem JavaScript-Ergebnis vergleichen können. Die meisten Beispiele sind einfach, aber es gibt auch ein Raytracer-Beispiel, das Sie sofort ausprobieren können. Ich empfehle, besonders die Beispiele "Verwenden von Klassen", "Verwenden von Vererbung" und "Verwenden von Generika" zu betrachten, indem Sie sie in der Combobox auswählen - dies sind nette Vorlagen, die Sie sofort in JavaScript verwenden können. Typoskript wird mit Angular verwendet.
Um die Kapselung lokaler Variablen, Funktionen usw. in JavaScript zu erreichen, empfehle ich, ein Muster wie das folgende zu verwenden (JQuery verwendet dieselbe Technik):
<html>
<head></head>
<body><script>
'use strict';
// module pattern (self invoked function)
const myModule = (function(context) {
// to allow replacement of the function, use 'var' otherwise keep 'const'
// put variables and function with local module scope here:
var print = function(str) {
if (str !== undefined) context.document.write(str);
context.document.write("<br/><br/>");
return;
}
// ... more variables ...
// main method
var _main = function(title) {
if (title !== undefined) print(title);
print("<b>last modified: </b>" + context.document.lastModified + "<br/>");
// ... more code ...
}
// public methods
return {
Main: _main
// ... more public methods, properties ...
};
})(this);
// use module
myModule.Main("<b>Module demo</b>");
</script></body>
</html>
Natürlich können und sollten Sie den Skriptcode in einer separaten *.js
Datei ablegen. Dies wird nur inline geschrieben, um das Beispiel kurz zu halten.
Selbstaufrufende Funktionen (auch bekannt als IIFE = Sofort aufgerufener Funktionsausdruck) werden hier ausführlicher beschrieben .