832 Stimmen

Verwendung von 'prototype' vs. 'this' in JavaScript?

Was ist der Unterschied zwischen

var A = function () {
    this.x = function () {
        //do something
    };
};

et

var A = function () { };
A.prototype.x = function () {
    //do something
};

0 Stimmen

Das Konzept des Schlüsselworts THIS wird hier explizit erläutert scotch.io/@alZami/verstehen-dieses-in-javascript

3 Stimmen

Die Lektüre "dieses" Threads zeigt, wie schrecklich JS ist und wie sehr seine Prinzipien für viele Entwickler unklar sind. Was genau ist falsch an einfacher zu verstehenden Sprachen? Ich denke, es ist an der Zeit, dass die Entwickler ihre Stimme erheben, um verwirrende Technologien abzulehnen, die keinen oder nur einen geringen Nutzen für das Geschäft oder die Entwicklungsarbeit haben.

14voto

Ely Punkte 10427

Ich möchte Ihnen eine umfassendere Antwort geben, die ich in einem JavaScript-Kurs gelernt habe.

Die meisten Antworten haben den Unterschied bereits erwähnt, d.h. beim Prototyping wird die Funktion mit allen (zukünftigen) Instanzen geteilt. Bei der Deklaration der Funktion in der Klasse wird hingegen für jede Instanz eine Kopie erstellt.

Im Allgemeinen gibt es kein Richtig oder Falsch, es ist eher eine Frage des Geschmacks oder eine Design-Entscheidung je nach Ihren Anforderungen. Der Prototyp ist jedoch die Technik, die zur objektorientierten Entwicklung verwendet wird, wie Sie hoffentlich am Ende dieser Antwort sehen werden.

Sie haben in Ihrer Frage zwei Muster aufgezeigt. Ich werde versuchen, zwei weitere zu erklären und gegebenenfalls die Unterschiede zu erläutern. Sie können sie gerne bearbeiten/erweitern. In allen Beispielen geht es um ein Autoobjekt, das einen Standort hat und sich bewegen kann.

Objekt-Dekorator-Muster

Ich bin nicht sicher, ob dieses Muster heute noch relevant ist, aber es existiert. Und es ist gut, es zu kennen. Man übergibt einfach ein Objekt und eine Eigenschaft an die Decorator-Funktion. Der Dekorator gibt das Objekt mit Eigenschaft und Methode zurück.

var carlike = function(obj, loc) {
    obj.loc = loc;
    obj.move = function() {
        obj.loc++;
    };
    return obj;
};

var amy = carlike({}, 1);
amy.move();
var ben = carlike({}, 9);
ben.move();

Funktionale Klassen

Eine Funktion in JavaScript ist ein spezialisiertes Objekt. Eine Funktion kann nicht nur aufgerufen werden, sondern sie kann auch Eigenschaften wie jedes andere Objekt speichern.

In diesem Fall Car ist eine Funktion ( auch piense en Objekt ), die in gewohnter Weise aufgerufen werden können. Sie hat eine Eigenschaft methods (das ist ein Objekt mit einer move Funktion). Wenn Car aufgerufen wird, wird die extend Funktion aufgerufen, die etwas zaubert und die Car Funktion (think object) mit den Methoden, die in methods .

Dieses Beispiel ist zwar anders, kommt aber dem ersten Beispiel in der Frage am nächsten.

var Car = function(loc) {
    var obj = {loc: loc};
    extend(obj, Car.methods);
    return obj;
};

Car.methods = {
    move : function() {
        this.loc++;
    }
};

var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();

Prototypische Klassen

Die ersten beiden Muster erlauben eine Diskussion über die Verwendung von Techniken zur Definition gemeinsamer Methoden oder die Verwendung von Methoden, die inline im Körper des Konstruktors definiert sind. In beiden Fällen hat jede Instanz ihre eigene move Funktion.

Das prototypische Muster eignet sich nicht für die gleiche Untersuchung, da die gemeinsame Nutzung von Funktionen über eine prototypische Delegation das eigentliche Ziel des prototypischen Musters ist. Wie bereits erwähnt, wird erwartet, dass es einen besseren Speicherplatzbedarf hat.

Es gibt jedoch einen Punkt, der interessant zu wissen ist: Jeder prototype Objekt hat eine praktische Eigenschaft constructor , die auf die Funktion (think object) zurückverweist, an die sie angehängt wurde.

Zu den letzten drei Zeilen:

In diesem Beispiel Car Links zu den prototype Objekt, das sich über constructor a Car selbst, d.h. Car.prototype.constructor es Car selbst. So können Sie herausfinden, welche Konstruktorfunktion ein bestimmtes Objekt erstellt hat.

amy.constructor scheitert und wird daher delegiert an Car.prototype die über die Eigenschaft Konstruktor verfügt. Und so amy.constructor es Car .

Außerdem, amy ist ein instanceof Car . El instanceof Operator funktioniert, indem er prüft, ob das Prototypobjekt des rechten Operanden ( Car ) kann an beliebiger Stelle im Prototyp des linken Operanden gefunden werden ( amy ) Kette.

var Car = function(loc) {
    var obj = Object.create(Car.prototype);
    obj.loc = loc;
    return obj;
};

Car.prototype.move = function() {
        this.loc++;
};

var amy = Car(1);
amy.move();
var ben = Car(9);
ben.move();

console.log(Car.prototype.constructor);
console.log(amy.constructor);
console.log(amy instanceof Car);

Manche Entwickler sind anfangs etwas verwirrt. Siehe untenstehendes Beispiel:

var Dog = function() {
  return {legs: 4, bark: alert};
};

var fido = Dog();
console.log(fido instanceof Dog);

El instanceof Operator kehrt zurück false denn Dog ist der Prototyp nirgendwo in fido Prototyp der Kette. fido ist ein einfaches Objekt, das mit einem Objektliteral erstellt wird, d.h. es delegiert einfach an Object.prototype .

Pseudoklassische Muster

Dies ist eigentlich nur eine andere Form des prototypischen Musters in vereinfachter Form und vertrauter für diejenigen, die zum Beispiel in Java programmieren, da es die new Konstrukteur.

Es tut dasselbe wie im prototypischen Muster, es ist nur syntaktischer Zucker über dem prototypischen Muster.

Der Hauptunterschied besteht jedoch darin, dass es in JavaScript-Engines implementierte Optimierungen gibt, die nur bei Verwendung des pseudoklassischen Musters gelten. Betrachten Sie das pseudoklassische Muster als eine wahrscheinlich schnellere Version des prototypischen Musters; die Objektbeziehungen sind in beiden Beispielen die gleichen.

var Car = function(loc) {
    this.loc = loc;
};

Car.prototype.move = function() {
        this.loc++;
};

var amy = new Car(1);
amy.move();
var ben = new Car(9);
ben.move();

Schließlich sollte es nicht allzu schwierig sein, zu erkennen, wie objektorientierte Programmierung durchgeführt werden kann. Es gibt zwei Abschnitte.

Ein Abschnitt, der gemeinsame Eigenschaften/Methoden im Prototyp (Kette) definiert.

Und einen weiteren Abschnitt, in dem Sie die Definitionen eintragen, die die Objekte voneinander unterscheiden ( loc Variable in den Beispielen).

Dies ermöglicht es uns, Konzepte wie Superklasse oder Unterklasse in JavaScript anzuwenden.

Sie können gerne etwas hinzufügen oder bearbeiten. Wenn es vollständiger ist, könnte ich daraus vielleicht ein Community-Wiki machen.

0 Stimmen

Ich will den sehr gründlichen Beitrag nicht schlecht machen, aber ich dachte, OO und prototypische Vererbung seien im Wesentlichen unterschiedliche Denkschulen.

0 Stimmen

Das sind sie, aber man kann OO mit verschiedenen Techniken/Gedanken "machen", nicht wahr?

0 Stimmen

Ich bin mir nicht ganz sicher. Viele sagen einfach, dass die prototypische Philosophie einfach anders ist, und viele versuchen, sie mit OO zu vergleichen, weil das die Denkschule ist, an die viele gewöhnt sind.

11voto

tvanfosson Punkte 506878

Ich glaube, dass @Matthew Crumley Recht hat. Sie sind funktionell wenn nicht sogar strukturell gleichwertig. Wenn Sie Firebug verwenden, um die Objekte zu betrachten, die mit new können Sie sehen, dass sie identisch sind. Meine Präferenz wäre jedoch die folgende. Ich vermute, dass es einfach mehr dem entspricht, was ich aus C#/Java gewohnt bin. Das heißt, man definiert die Klasse, definiert die Felder, den Konstruktor und die Methoden.

var A = function() {};
A.prototype = {
    _instance_var: 0,

    initialize: function(v) { this._instance_var = v; },

    x: function() {  alert(this._instance_var); }
};

EDITAR Ich wollte damit nicht andeuten, dass der Geltungsbereich der Variablen privat ist, ich wollte nur veranschaulichen, wie ich meine Klassen in Javascript definiere. Der Variablenname wurde geändert, um dies widerzuspiegeln.

2 Stimmen

_instance_var wie in der initialize y x methods do not refer to the _instance_var`-Eigenschaft auf einer A Instanz, sondern zu einer globalen Instanz. verwenden this._instance_var wenn Sie die Funktion _instance_var Eigenschaft eines A Instanz.

2 Stimmen

Das Lustige daran ist, dass Benry auch einen solchen Fehler gemacht hat, der nach zwei Jahren ebenfalls aufgedeckt wurde :p

10voto

Devgr Punkte 111

Wie bereits in anderen Antworten erwähnt, ist dies eine Frage der Leistung, da die Funktion im Prototyp von allen Instanziierungen gemeinsam genutzt wird, anstatt dass die Funktion für jede Instanziierung neu erstellt wird.

Ich habe ein jsperf zusammengestellt, um dies zu zeigen. Es gibt einen dramatischen Unterschied in der Zeit, die es braucht, um die Klasse zu instanziieren, obwohl es wirklich nur relevant ist, wenn Sie viele Instanzen machen.

http://jsperf.com/functions-in-constructor-vs-prototype

10voto

牛さん Punkte 2734

Denken Sie an statisch typisierte Sprachen, Dinge auf prototype statisch sind und Dinge auf this sind instanzbezogen.

-1voto

Tiago Martins Peres Punkte 12271

Wenn Sie den Prototyp verwenden, wird die Funktion nur einmal in den Speicher geladen (unabhängig von der Anzahl der Objekte, die Sie erstellen) und Sie können die Funktion jederzeit überschreiben.

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