2012-07-02 7 views
9

Ein Prototyp wird verwendet, um Eigenschaften und Methoden für eine Klasse von Objekten zu deklarieren. Ein Vorteil der Verwendung eines Prototyps besteht darin, dass Speicher gespart wird, da alle Instanzen einer Klasse auf die Eigenschaften und Methoden des Prototyps verweisen, die Speicher sparen und es ermöglichen, dass Eigenschaften von allen Instanzen einer Klasse als statisch behandelt werden.Gibt es einen Vorteil für die Verwendung von Prototypen anstatt Eigenschaften für das Objekt selbst zu deklarieren?

Prototyp wird für Vererbung durch Prototypverkettung verwendet.

Meine Frage ist sehr einfach. Warum Prototyp überhaupt verwenden, wenn Sie nur tun können:

function car() { 
    this.engine = "v8"; 
} 
function mustang() { 
    // nm, no good way to inherit without using prototypes 
} 

Ist das richtig? So ist der primäre Zweck der Prototypen ist dreifach:

  1. Konserve Speicher
  2. bieten statische Eigenschaften
  3. ist der einzige Weg für eine Referenz-Typ aus einer Superklasse erben
+1

Ich bin mir nicht sicher, was Sie fragen ... Sie scheinen zu sagen "Sie können einfach tun ...", aber dann in dem Kommentar in diesem Skript sagen Sie "kein guter Weg, es zu tun" . Widerspricht sich das nicht selbst? – Joeytje50

+1

Ich glaube, er merkte, dass seine Gedanken während der Frage falsch lagen. Jedenfalls war er nicht auf Stapelwechsel, seit er die Frage vor 18 Monaten gestellt hatte, also hatte er keinen Sinn, sich an ihn zu wenden. Es war ich, der sich immer noch fragt ... – Aerovistae

+0

Wenn du keinen Prototyp verwendest, kannst du die Funktion tun mustang() {car.apply (this); } – Serge

Antwort

0

Prototyping viel ist mehr als das. Sie können auch Klassen und bereits vorhandene Instanzen von Objekten zur Laufzeit mit Methoden und Eigenschaften erweitern.

Dies sollte es in eine sehr verständlichen Weise erklären: http://javascript.info/tutorial/inheritance

0

Wenn Sie über folgende Konventionen kümmern, damit die Menschen (und Sie auf dem Weg) tatsächlich den Code verstehen, kann man nicht this.engine="v8" im Konstruktor setzen sollte. Prototyp soll Eigenschaften für jedes einzelne Auto definieren, und der Konstruktor soll einzelne Instanzen definieren. Also warum würdest du etwas, das für jeden Fall im Konstruktor stimmt? Dies gehört in den Prototyp. Es gibt etwas, das gesagt werden kann, um die Dinge an ihren richtigen Platz zu stellen, selbst wenn beide Dinge dazu führen, dasselbe zu erreichen. Ihr Code wird für Sie und andere verständlich sein.

1

In Bezug auf Ihre drei Punkte:

  1. Prototypen sind nicht unbedingt mehr performant, vor allem für Prototypen-Ketten, die lang werden oder viele Mitglieder enthalten. Je kleiner der Prototyp und je kürzer die Kette, desto mehr kann der Compiler des Browsers ihn optimieren. Letztendlich muss diese Frage nach individuellen Anwendungen, ihren individuellen Bedürfnissen und den Browsern gefragt werden (die in der Leistung stark variieren können).
  2. Nach Definition benötigen statische Elemente Objekte. Das heißt, statische Elemente gehören zu einem Objekt selbst und nicht zu einer bestimmten Instanz. Objekte sind die einzige Möglichkeit, statische Eigenschaften in JavaScript zu erstellen. Beachten Sie, dass Objektliterale, die eine "spezielle" Art von Objekt sind, im Wesentlichen statisch sind.
  3. Man könnte seinen eigenen Objekttyp implementieren, der etwas wie Vererbung zulässt (d. H. jQuery.extend), aber soweit es Referenztypen gibt, sind Prototypen die einzige Möglichkeit, Vererbung zu erzeugen.
+0

Zeigt das nicht, dass der Prototyp die anderen ausführt? Nur Chrome 29 und 30 sind ungefähr gleich. Hier geht es um Operationen pro Sekunde und zeigt keinen Speicherverbrauch. In Punkt 3; Der einzige Weg, "jemandInployer-Instanz von Person" wahr zu haben, ist, den Prototyp – HMR

+0

HMR zu verwenden, danke, dass Sie das eingefangen haben - es war ein schlechtes Beispiel für mich. Ich habe die Antwort bearbeitet, um den Grund zu erklären. –

+0

Ja, es könnte einen negativen Einfluss auf die Leistung https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain#Performance in einer Schleife haben, die Methoden hoch oben auf der Prototyp-Kette aufruft, die Sie vielleicht bemerken Dies. – HMR

2

Konserve Speicher

Ja, es funktioniert, wenn Sie Hunderte von Instanzen von Auto erstellen und sie alle haben ihre eigenen Funktionen (die ihre eigenen Verschluss Bereiche haben) werden Sie mehr Speicher verbrauchen.

Es kann keine Referenz gefunden werden, aber es wurde vorgeschlagen, dass Chrome Konstruktorfunktionen optimiert, die Prototypen besser als Konstruktorfunktionen mit allem im Konstruktorkörper verwenden.

bieten statische Eigenschaften

Static ist mehr wie Date.now(), jede Instanz hat Mitglieder aus dem Prototyp kann aber auf der Instanz aufgerufen werden.

ist der einzige Weg für eine Referenz-Typ aus einer Superklasse erben

Sie mit Parent.apply(this,arguments); in Kinder erben können, aber es macht erstreckt Elternteil Funktionen komplizierter und nicht childInstance instanceof Parent wahr macht. Was dieser Code tut, ist Parent-Code mit der zu erstellenden Child-Instanz als aufrufendes Objekt (this). Die Vererbung erfolgt normalerweise an 2 Orten.

  1. Im Kinderkörper Parent.apply(this,arguments); Verwendung Eltern Initialisierungscode und machen übergeordnete Instanz Mitglieder sein Kind Instanz Mitglieder (zum Beispiel: this.name) wieder.
  2. Setzen von Child.prototype auf seichte Kopie von Parent.prototype Child.prototype=Object.create(Parent.prototype);Child.prototype.constructor=Child; Dies stellt sicher, dass gemeinsame Parent-Mitglieder auf Child-Instanzen verfügbar sind (wie die Funktion getName).

Diese Punkte werden hier näher erläutert: https://stackoverflow.com/a/16063711/1641941

0

Ihre Punkte in Bezug auf:

  1. Es ist auf jeden Fall eine Leistungssteigerung, vor allem in Bezug auf Funktionen - es ist viel besser Funktionen auf dem Prototyp zu erklären .
  2. Ich denke, Sie wollten "öffentliche" Eigenschaften sagen, so dass Informationen durch Schreiben some_instance.foo abgerufen werden. "Statische" Eigenschaften/Methoden sind unterschiedlich (siehe unten).
  3. Korrekt. Vererbung kann nur wirklich vom Prototyp her geschehen.

Lassen Sie mich einige Dinge erklären, um zu sehen, ob dies hilft. Das Erstellen neuer "Klassen" in Javascript ist ein ziemlich einfacher Prozess.

var MyClass = new Function(); 

An diesem Punkt ist der Motor Ihres neuen Klasse bewusst und weiß, „was zu tun ist“ (in Bezug auf die Leistung), wenn es neue Instanzen Ihrer „Klasse“ erstellt.

var my_instance = new MyClass(); 

Wenn Sie den Prototyp ändern möchten, können Sie dies tun, und wissen, dass jede Instanz aktualisiert bekommen wird, weil sie alle den gleichen Prototyp teilen.

MyClass.prototype.name = "default name"; 
console.log(my_instance.name); //=> default name 

Jetzt der Motor weiß, dass es ein „Name“ Eigenschaft, die ein String-Wert erwartet ... es wird die Ressourcen für alle neuen und bestehenden Instanzen Ihrer Klasse zuzuteilen ... was sehr praktisch ist .Beachten Sie, dass das Ändern des Prototyps einer vorhandenen "Klasse" wie dieser ein teurer Prozess ist und nicht häufig ausgeführt werden sollte (aber haben Sie auch keine Angst, dies zu tun).

ich für die Leistung Vor-und Nachteile erklären Ad-hoc-Eigenschaften/Methoden auf einer Instanz nicht wirklich sprechen kann:

my_instance.foo = function() { /* this is not in the prototype chain */ }; 

Meine Vermutung ist, dass dies für den Motor ist ziemlich einfach und ist keine große Sache, es sei denn, Sie tun dies für Zehntausende von Objekten zur gleichen Zeit.

Der Hauptvorteil des Prototyp IMO ist, dass Sie Code schreiben können eine Methode der Funktionalität zu erweitern und wissen, dass alle Instanzen der „Klasse“ werden entsprechend aktualisiert werden:

var old_foo = MyClass.prototype.foo; 
MyClass.prototype.foo = function() { 
    /* new business logic here */ 

    // now call the original method. 
    old_foo.apply(this, arguments); 
}; 

In Bezug auf „statisch“

Eigenschaften Sie init/zerstören Methoden wie diese erstellen können

// example static property 
MyClass.num_instances = 0; 

Jetzt:

MyClass.prototype.init = function() { 
    this.constructor.num_instances++; 
}; 

MyClass.prototype.destroy = function() { 
    this.constructor.num_instances--; 
}; 

// and call the init method any time you create a new instance 
my_instance.init(); 
console.log(MyClass.num_instances); //=> 1 

var instance_2 = new MyClass(); 
instance_2.init(); 
console.log(MyClass.num_instances); //=> 2 

instance_2.destroy(); 
console.log(MyClass.num_instances); //=> 1 
Sie die auf der "Klasse" (Konstruktor) selbst erklären

Hoffe, dass hilft.

0

(1) Ich denke nicht, Speicher zu sparen allein ist ein guter Grund, um .prototype zu verwenden, es sei denn, Sie werden wirklich extrem mit Duplizieren von Objekten.

(2) Die Idee der statischen Eigenschaften ist nicht wirklich ein Grund, .prototype (IMHO) zu verwenden, weil es sich nicht wie eine traditionelle statische Eigenschaft verhält. Sie (so weit ich weiß) benötigen immer eine Objektinstanz, bevor Sie auf die Eigenschaft "static" zugreifen können, was sie überhaupt nicht statisch macht.

function Car() {} 
Car.prototype.Engine = "V8"; 
// I can't access Car.Engine... I'll always need an instance. 
alert(new Car().Engine); 
// or 
var car1 = new Car(); 
alert(car1.Engine); //you always need an instance. 
//unless you wanted to do 
alert(Car.prototype.Engine); //this is more like a static property, but has an 
//unintended consequence that every instance of Car also receives a .Engine 
//behavior, so don't do this just to create a "static property." 

Es soll beachtet werden, dass diese „statisch“ Idee nicht nur auf Eigenschaften gilt, sondern für alle Mitglieder, die Methoden (Funktionen), aus einer traditionellen OO Perspektive umfasst.

Es ist besser, an Prototypen (wieder IMHO) als injected singleton Objekte mit Verhaltensweisen zu denken, die an Instanzobjekte angehängt werden. Alle Instanzen von Car() können ihre eigenen Instanzmitglieder haben, aber jede Instanz von Car() wird auch automatisch mit allen Mitgliedern/Verhaltensweisen des Car.prototypes "injiziert". Es ist technisch nicht dasselbe, aber ich finde es praktisch, auf diese Weise über Prototypen nachzudenken.

//define Car and Car.GoFast 
function Car() {} 
Car.prototype.GoFast = function() { alert('vroom!'); }; 

var car1 = new Car(); 
var car2 = new Car(); 

car1.GoFast(); 
car2.GoFast(); //both call to same GoFast implementation on Car.prototype 

//change the GoFast implementation 
Car.prototype.GoFast = function() { alert('vvvvvrrrrroooooooooommmmm!!!!!'); }; 

car1.GoFast(); 
car2.GoFast(); //both have been "updated" with the new implementation because 
//both car1 and car2 are pointing to the same (singleton) Car.prototype object! 

Car.prototype verhält wie ein Singleton-Objekt, dessen Mitglieder/Verhaltensweisen in Beispiel Objekte des Typs Auto injiziert wurden.

(3) Prototypen sollten nicht wegen Vererbung verwechselt werden. Sie können Verhalten erhalten, das als Vererbung erscheint, aber nicht. Die Member/Verhaltensweisen auf dem Prototyp verbleiben auf dem Prototypobjekt. Sie werden nicht Mitglieder/Verhaltensweisen Ihrer abgeleiteten Klasse, wie wahre Vererbung. Deshalb beschreibe ich es eher so, als würde der Prototyp in deine Instanz "injiziert" werden.

function Car() {} 
Car.prototype.Engine = "V8"; 
var car1 = new Car(); 
var car2 = new Car(); 

alert(car1.Engine); //alerts "V8" 
//There is no "Engine" variable defined within the instance scope of 'car1'. 
//Javascript searches the scope of car1's Type.prototype object to find 'Engine'. 
//Equivalent to: Object.getPrototypeOf(car1).Engine 

//But if we create 'Engine' within the scope of car1 
car1.Engine = "V6"; //Car.prototype was never accessed or updated 
alert(car1.Engine); //we get "V6" 
alert(car2.Engine); //we still get "V8" 
alert(Object.getPrototypeOf(car1).Engine); //we still get "V8"! 

Also die Frage direkt zu beantworten: Gibt es einen Nutzen Prototyp statt erklärt Eigenschaften für das Objekt selbst zu verwenden?

Ja, wenn Sie die Verhaltensimplementierung unter Instanzobjekten eines bestimmten Typs teilen möchten.Als Zufall reduzieren Sie Ihren Speicherbedarf, aber das ist kein Grund, Prototypen zu verwenden. Weder "statische Eigenschaften erstellen" (was sie nicht sind), noch Vererbung (was nicht ist).