707 Stimmen

Welche Techniken können verwendet werden, um eine Klasse in JavaScript zu definieren, und was sind ihre Nachteile?

Ich ziehe es vor, OOP in großen Projekten wie dem, an dem ich gerade arbeite, zu verwenden. Ich muss mehrere Klassen in JavaScript erstellen, aber wenn ich mich nicht irre, gibt es zumindest ein paar Möglichkeiten, das zu tun. Wie sieht die Syntax aus und warum sollte man es auf diese Weise tun?

Ich möchte die Verwendung von Bibliotheken von Drittanbietern vermeiden - zumindest am Anfang.
Auf der Suche nach weiteren Antworten fand ich den Artikel Objektorientierte Programmierung mit JavaScript, Teil I: Vererbung - Doc JavaScript das die objektorientierte Programmierung in JavaScript behandelt. Gibt es einen besseren Weg, um Vererbung durchzuführen?

1 Stimmen

Hinweis: Dies ist ein Duplikat von stackoverflow.com/questions/355848

3 Stimmen

Ich persönlich mag es, Klassenmitglieder innerhalb des Funktionskörpers zu deklarieren. Ich verwende die Technik des "Fixierens des This", um einen Abschluss zu erstellen, der sich mehr wie eine Klasse verhält. Ich habe ein ausführliches Beispiel in meinem Blog: ncombo.wordpress.com/2012/12/30/

1 Stimmen

Ich habe die meisten C++ OOP-Funktionen mit einer einfachen und natürlichen Syntax auf JavaScript portiert. Siehe meine Antwort hier: stackoverflow.com/a/18239463/1115652

755voto

Kenan Banks Punkte 196831

Hier ist der Weg, um dies ohne externe Bibliotheken zu tun:

// Define a class like this
function Person(name, gender){

   // Add object properties like this
   this.name = name;
   this.gender = gender;
}

// Add methods like this.  All Person objects will be able to invoke this
Person.prototype.speak = function(){
    alert("Howdy, my name is" + this.name);
};

// Instantiate new objects with 'new'
var person = new Person("Bob", "M");

// Invoke methods like this
person.speak(); // alerts "Howdy, my name is Bob"

Die eigentliche Antwort ist jedoch viel komplexer als das. Zum Beispiel gibt es in JavaScript keine Klassen. JavaScript verwendet eine prototype -basierten Vererbungsschema.

Darüber hinaus gibt es zahlreiche populäre JavaScript-Bibliotheken, die eine eigene Art der Annäherung an klassenähnliche Funktionen in JavaScript haben. Sie sollten sich zumindest die folgenden Bibliotheken ansehen Prototyp y jQuery .

Die Entscheidung, welches davon das "Beste" ist, ist eine gute Möglichkeit, einen heiligen Krieg auf Stack Overflow zu beginnen. Wenn Sie ein größeres JavaScript-lastiges Projekt in Angriff nehmen, lohnt es sich auf jeden Fall, eine beliebte Bibliothek zu erlernen und es auf ihre Art zu tun. Ich bin ein Prototype-Typ, aber Stack Overflow scheint zu jQuery zu neigen.

Soweit es nur "einen Weg, es zu tun", ohne Abhängigkeiten von externen Bibliotheken, die Art, die ich schrieb, ist ziemlich genau es.

48 Stimmen

Aber es funktioniert nicht wie die Sprache X, in der ich gelernt habe, wie ein Ding, das zur Erstellung von Objektinstanzen verwendet wird, wirklich funktionieren sollte :(

2 Stimmen

Según developer.mozilla.org/de-US/docs/Web/JavaScript/ die Eigenschaften sollten auch dem Prototyp hinzugefügt werden (" Person.prototype.name= ''; ")

1 Stimmen

@DaveD - vielleicht war es so, aber es scheint nicht mehr so zu sein ?

214voto

Jörg W Mittag Punkte 349574

Der beste Weg, eine Klasse in JavaScript zu definieren, ist, keine Klasse zu definieren.

Ganz im Ernst.

Es gibt verschiedene Arten der Objektorientierung, einige davon sind:

  • klassenbasierte OO (zuerst eingeführt durch Smalltalk)
  • Prototyp-basierte OO (zuerst von Self eingeführt)
  • Multimethoden-basierte OO (zuerst eingeführt durch CommonLoops, glaube ich)
  • prädikatsbasierte OO (keine Ahnung)

Und wahrscheinlich noch andere, von denen ich nichts weiß.

JavaScript implementiert prototypenbasierte OO. In der prototypenbasierten OO werden neue Objekte durch Kopieren anderer Objekte erstellt (anstatt aus einer Klassenvorlage instanziiert zu werden), und Methoden befinden sich direkt in Objekten anstatt in Klassen. Die Vererbung erfolgt über Delegation: Wenn ein Objekt keine Methode oder Eigenschaft hat, wird es über seine(n) Prototyp(en) (d. h. das Objekt, von dem es geklont wurde) nachgeschlagen, dann über die Prototypen des Prototyps und so weiter.

Mit anderen Worten: Es gibt keine Klassen.

JavaScript hat eine schöne Abwandlung dieses Modells: Konstruktoren. Sie können nicht nur Objekte durch Kopieren bestehender Objekte erstellen, sondern sie auch sozusagen "aus dem Nichts" konstruieren. Wenn Sie eine Funktion mit der Anweisung new Schlüsselwort, wird diese Funktion zu einem Konstruktor und die this Schlüsselwort nicht auf das aktuelle Objekt, sondern auf ein neu erstelltes "leeres" Objekt verweist. Sie können also ein Objekt nach Belieben konfigurieren. Auf diese Weise können JavaScript-Konstruktoren eine der Rollen von Klassen in der traditionellen klassenbasierten OO übernehmen: Sie dienen als Vorlage oder Blaupause für neue Objekte.

JavaScript ist eine sehr mächtige Sprache, so dass es recht einfach ist, ein klassenbasiertes OO-System zu implementieren innerhalb von JavaScript wenn Sie das wollen. Allerdings sollten Sie dies nur tun, wenn Sie wirklich einen Bedarf dafür haben und nicht nur, weil Java es so macht.

0 Stimmen

"Wenn Sie eine Funktion mit dem Schlüsselwort new aufrufen, wird diese Funktion zu einem Konstruktor, und das Schlüsselwort this verweist nicht auf das aktuelle Objekt, sondern auf ein neu erstelltes "leeres" Objekt". Wenn Sie eine Funktion ohne das Schlüsselwort new aufrufen, verweist this auf den aufrufenden Kontext, standardmäßig auf das globale Objekt (window). Im Strict-Modus ist undefined der Standardwert. call, apply und bind haben den aufrufenden Kontext als ersten Parameter. developer.mozilla.org/de-US/docs/Web/JavaScript/Reference/

86voto

Dale Punkte 5507

ES2015-Klassen

In der ES2015-Spezifikation können Sie die Klassensyntax verwenden, die lediglich das Prototypensystem überlagert.

class Person {
  constructor(name) {
    this.name = name;
  }
  toString() {
    return `My name is ${ this.name }.`;
  }
}

class Employee extends Person {
  constructor(name, hours) {
    super(name);
    this.hours = hours;
  }
  toString() {
    return `${ super.toString() } I work ${ this.hours } hours.`;
  }
}

Vorteile

Der Hauptvorteil besteht darin, dass statische Analysetools diese Syntax leichter anvisieren können. Auch für andere, die aus klassenbasierten Sprachen kommen, ist es einfacher, die Sprache als Polyglott zu verwenden.

Vorbehalte

Achten Sie auf die derzeitigen Einschränkungen. Um Privateigentum zu erreichen, muss man auf Verwendung von Symbolen oder WeakMaps . In zukünftigen Versionen werden die Klassen höchstwahrscheinlich um diese fehlenden Funktionen erweitert werden.

Unterstützung

Browser-Unterstützung ist im Moment nicht sehr gut (wird von fast allen außer dem IE unterstützt), aber Sie können diese Funktionen jetzt mit einem Transpiler wie Babel .

Ressourcen

56voto

Daniel X Moore Punkte 13868

Ich bevorzuge das Buch von Daniel X. Moore {SUPER: SYSTEM} . Dies ist eine Disziplin, die Vorteile wie echte Instanzvariablen, traitbasierte Vererbung, Klassenhierarchien und Konfigurationsoptionen bietet. Das nachstehende Beispiel veranschaulicht die Verwendung echter Instanzvariablen, was meiner Meinung nach der größte Vorteil ist. Wenn Sie keine Instanzvariablen benötigen und sich mit öffentlichen oder privaten Variablen begnügen, gibt es wahrscheinlich einfachere Systeme.

function Person(I) {
  I = I || {};

  Object.reverseMerge(I, {
    name: "McLovin",
    age: 25,
    homeState: "Hawaii"
  });

  return {
    introduce: function() {
      return "Hi I'm " + I.name + " and I'm " + I.age;
    }
  };
}

var fogel = Person({
  age: "old enough"
});
fogel.introduce(); // "Hi I'm McLovin and I'm old enough"

Wow, das ist für sich genommen nicht wirklich nützlich, aber sehen Sie sich das Hinzufügen einer Unterklasse an:

function Ninja(I) {
  I = I || {};

  Object.reverseMerge(I, {
    belt: "black"
  });

  // Ninja is a subclass of person
  return Object.extend(Person(I), {
    greetChallenger: function() {
      return "In all my " + I.age + " years as a ninja, I've never met a challenger as worthy as you...";
    }
  });
}

var resig = Ninja({name: "John Resig"});

resig.introduce(); // "Hi I'm John Resig and I'm 25"

Ein weiterer Vorteil ist die Möglichkeit, Module und die Vererbung von Eigenschaften zu nutzen.

// The Bindable module
function Bindable() {

  var eventCallbacks = {};

  return {
    bind: function(event, callback) {
      eventCallbacks[event] = eventCallbacks[event] || [];

      eventCallbacks[event].push(callback);
    },

    trigger: function(event) {
      var callbacks = eventCallbacks[event];

      if(callbacks && callbacks.length) {
        var self = this;
        callbacks.forEach(function(callback) {
          callback(self);
        });
      }
    },
  };
}

Ein Beispiel dafür, dass die Personenklasse das bindungsfähige Modul enthält.

function Person(I) {
  I = I || {};

  Object.reverseMerge(I, {
    name: "McLovin",
    age: 25,
    homeState: "Hawaii"
  });

  var self = {
    introduce: function() {
      return "Hi I'm " + I.name + " and I'm " + I.age;
    }
  };

  // Including the Bindable module
  Object.extend(self, Bindable());

  return self;
}

var person = Person();
person.bind("eat", function() {
  alert(person.introduce() + " and I'm eating!");
});

person.trigger("eat"); // Blasts the alert!

Offenlegung: Ich bin Daniel X. Moore und dies ist meine {SUPER: SYSTEM} . Es ist der beste Weg, um eine Klasse in JavaScript zu definieren.

0 Stimmen

@DanielXMoore "Instanzvariablen werden von einzelnen Instanzen einer Klasse gemeinsam genutzt" Das sind keine Instanzvariablen, sondern statische/Klassenvariablen.

2 Stimmen

@JAB Das ist nicht korrekt, statische/Klassenvariablen werden gemeinsam von todo Instanzen einer Klasse. Jede Instanz hat ihre eigenen Instanzvariablen.

0 Stimmen

(Anders ausgedrückt, wenn man die normale Bedeutung des Begriffs "Instanzvariable" verwendet, ist die Frage, ob eine Variable eine Instanzvariable ist oder nicht, orthogonal zum Grad der Zugänglichkeit der Variablen).

41voto

liammclennan Punkte 5245
var Animal = function(options) {
    var name = options.name;
    var animal = {};

    animal.getName = function() {
        return name;
    };

    var somePrivateMethod = function() {

    };

    return animal;
};

// usage
var cat = Animal({name: 'tiger'});

0 Stimmen

Dies ist ein sehr eleganter Weg, um eine brauchbare Objektstruktur aufzubauen, ohne etwas importieren zu müssen. Ich habe das Klassensystem von Resig verwendet, aber vielleicht gefällt mir das besser. Ich danke Ihnen.

29 Stimmen

Das Problem bei diesem Ansatz ist, dass jedes Mal, wenn Sie eine neue Animal-Instanz erstellen, die Funktionen neu definiert werden, anstatt sie nur einmal mit prototype zu definieren.

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