2015-03-24 11 views
11

In der Vergangenheit, als „Klassen“ in JavaScript erstellen, habe ich es so gemacht:Verwirrung darüber, wie Klassen zu schaffen, in JavaScript

function Dog(name){ 
    this.name=name; 
    this.sound = function(){ 
     return "Wuf"; 
    }; 
} 

aber ich sah nur jemand wie diese stattdessen tun:

var Dog = (function() { 
    function Dog(name) { 
     this.name = name; 
    } 
    Dog.prototype.sound = function() { 
     return "Wuf"; 
    }; 
    return Dog; 
})(); 

Können Sie es auf beide Arten tun, oder ist es so, dass ich es falsch gemacht habe? In diesem Fall, warum? Und was genau ist der Unterschied zwischen den beiden in Bezug auf was wir am Ende haben? In beiden Fällen können wir ein Objekt erstellen, indem wir sagen:

var fido = new Dog("Fido"); 
fido.sound(); 

Ich hoffe, jemand wird mich erleuchten.

+0

Weitere Informationen zur Verwendung von Konstruktorfunktionen und Prototypen finden Sie hier: http://StackOverflow.com/a/16063711/1641941 hoffe, es hilft – HMR

Antwort

15

Es gibt zwei wichtige Unterschiede zwischen Ihrem und ihrem Weg.

  1. Wrapping in einem selbstaufrufende Funktion ((function() { ... })();)
  2. Verwenden der .prototype Eigenschaft über this. für Methoden.

Wrapping Dinge in einer selbst rufenden Funktion, dann das Ergebnis Zuweisung (wie in der return Anweisung auf eine Variable definiert wird die module pattern genannt. Es ist ein gemeinsames Muster ist ist mehr Spielraum zu gewährleisten. Kontrollierte

Dog.prototype.sound = function() {} Verwendung ist bevorzugt zu this.sound = function(). der Unterschied besteht darin, dass Dog.prototype.sound einmal für alle Objekte mit dem Dog Konstruktor definiert ist, und die this.sound = function() {}für jeden Hund Objekt erneut definiert ist erstellt.

Die Faustregel lautet: Dinge, die für ein Objekt individuell sind (normalerweise seine Eigenschaften) sind unter this zu definieren, während Dinge, die für alle Objekte desselben Typs (normalerweise Funktionen) freigegeben sind, definiert werden sollen der Prototyp.

4

Mit Ihrem Code erstellen Sie eine neue Funktion sound für jede neue Dog Instanz, die gerade erstellt wird. Javascript prototype vermeidet dies, indem es nur eine einzelne Funktion erstellt, die alle Objektinstanzen teilen; im Grunde klassische Vererbung.

Im zweiten Code, den du zeigst, ist das nur zusätzlich in einem IIFE verpackt, was in diesem Fall nicht viel bringt.

3

Die erste ist die traditionelle Methode zum Erstellen eines Konstruktors. Der zweite ein direkt aufgerufener Funktionsausdruck, der einen Konstruktor zurückgibt. Mit dieser Methode können Sie Variablen innerhalb des Moduls behalten, ohne in den globalen Geltungsbereich zu gelangen, was ein Problem darstellen könnte.

Und was genau ist der Unterschied zwischen den beiden in Bezug auf was wir am Ende sind?

Sie beide, wie Sie gesehen haben, haben das gleiche Ergebnis. Die anderen haben über prototype gesprochen, also werde ich es hier nicht erwähnen.

+0

Es gibt einen kleinen Unterschied im Ergebnis. Das zweite Beispiel kann aufgrund der Verwendung von "Prototyp" als besser angesehen werden. –

+1

Nicht wirklich einen Downvote wert tho, war es? – Andy

+0

Nein, das war ich nicht. –

2

Die zweite ist vorzuziehen, weil sie den prototypischen Vererbungsmechanismus von Javascript ausnutzt.

Prototypen

Javascript Vererbung ist eine Ursache für Verwirrung, aber es ist eigentlich recht einfach: jedes Objekt einen Prototyp hat, das ist ein Objekt, das wir überprüfen, wenn wir versuchen, eine Eigenschaft zuzugreifen, nicht auf dem Original Objekt. Der Prototyp wird selbst einen Prototyp haben; in einem einfachen Fall, wie Dog, wird dies wahrscheinlich Object.prototype sein.

In beiden Beispielen, aufgrund der newoperator works, enden wir mit einer Prototyp-Kette, die wie folgt aussieht: fido->Dog.prototype->Object.prototype. Also, wenn wir versuchen, nach der name Eigenschaft auf Fido zu suchen, werden wir es genau dort auf dem Gegenstand finden. Wenn wir andererseits nach der hasOwnProperty Eigenschaft suchen, werden wir es auf Fido nicht finden, können es unter Dog.prototype nicht finden und erreichen dann Object.prototype, wo wir es finden werden.

Im Fall von sound definieren Ihre Beispiele es an zwei verschiedenen Orten: im ersten Fall fido und jeder andere Hund, den wir erstellen, wird eine eigene Kopie der Funktion haben. Im zweiten Fall wird Dog.prototype eine einzelne Kopie der Funktion haben, auf die einzelne Hunde beim Aufruf der Methode zugreifen. Dies vermeidet die Verschwendung von Ressourcen beim Speichern von Duplikaten der sound-Funktion.

Es bedeutet auch, dass wir die Prototypkette erweitern können; vielleicht wollen wir eine Corgi Klasse, die die sound Funktion von Dog erbt. Im zweiten Fall können wir einfach sicherstellen, dass Dog.prototype in der Prototypkette Corgi.prototype ist; In der ersten mussten wir einen tatsächlichen Hund erstellen und ihn in die Prototypkette einfügen.

Verwandte Themen