JavaScript: Class.method vs. Class.prototype.method


498

Was ist der Unterschied zwischen den folgenden beiden Erklärungen?

Class.method = function () { /* code */ }
Class.prototype.method = function () { /* code using this.values */ }

Ist es in Ordnung, sich die erste Anweisung als Deklaration einer statischen Methode und die zweite Anweisung als Deklaration einer Instanzmethode vorzustellen?

Antworten:


695

Ja, die erste Funktion hat keine Beziehung zu einer Objektinstanz dieser Konstruktorfunktion . Sie können sie als 'statische Methode' betrachten .

In JavaScript sind Funktionen erstklassige Objekte, dh Sie können sie wie jedes Objekt behandeln. In diesem Fall fügen Sie dem Funktionsobjekt nur eine Eigenschaft hinzu .

Die zweite Funktion, wenn Sie den Prototyp der Konstruktorfunktion erweitern, steht allen mit dem newSchlüsselwort erstellten Objektinstanzen zur Verfügung , und der Kontext innerhalb dieser Funktion (das thisSchlüsselwort) bezieht sich auf die tatsächliche Objektinstanz, in der Sie sie aufrufen.

Betrachten Sie dieses Beispiel:

// constructor function
function MyClass () {
  var privateVariable; // private member only available within the constructor fn

  this.privilegedMethod = function () { // it can access private members
    //..
  };
}

// A 'static method', it's just like a normal function 
// it has no relation with any 'MyClass' object instance
MyClass.staticMethod = function () {};

MyClass.prototype.publicMethod = function () {
  // the 'this' keyword refers to the object instance
  // you can access only 'privileged' and 'public' members
};

var myObj = new MyClass(); // new object instance

myObj.publicMethod();
MyClass.staticMethod();

1
Aber warum ist Function.prototype.method == Function.method?
Raghavendra

1
@ Raghavendra ist es nicht
Zorgatone

1
@ Menda Ihr Link ist tot
Eugen Sunic

19

Wenn Sie mehr als eine Instanz von MyClass erstellen, befindet sich immer noch nur eine Instanz von publicMethod im Speicher. Bei privilegedMethod werden jedoch viele Instanzen erstellt, und staticMethod hat keine Beziehung zu einer Objektinstanz.

Deshalb sparen Prototypen Speicher.

Wenn Sie die Eigenschaften des übergeordneten Objekts ändern und die entsprechende Eigenschaft des Kindes nicht geändert wurde, wird sie aktualisiert.


15

Für visuelle Lernende beim Definieren der Funktion ohne .prototype

ExampleClass = function(){};
ExampleClass.method = function(customString){
             console.log((customString !== undefined)? 
                          customString : 
                          "called from func def.");}
ExampleClass.method(); // >> output: `called from func def.`  

var someInstance = new ExampleClass();
someInstance.method('Called from instance');
    // >> error! `someInstance.method is not a function`  

Mit dem gleichen Code, wenn .prototypehinzugefügt wird,

ExampleClass.prototype.method = function(customString){
             console.log((customString !== undefined)? 
                          customString : 
                          "called from func def.");}
ExampleClass.method();  
      // > error! `ExampleClass.method is not a function.`  

var someInstance = new ExampleClass();
someInstance.method('Called from instance');
                 // > output: `Called from instance`

Um es klarer zu machen,

ExampleClass = function(){};
ExampleClass.directM = function(){}  //M for method
ExampleClass.prototype.protoM = function(){}

var instanceOfExample = new ExampleClass();

ExampleClass.directM();      works
instanceOfExample.directM();   x Error!

ExampleClass.protoM();     x Error!
instanceOfExample.protoM();   works

**** Beachten Sie für das obige Beispiel, dass someInstance.method () nicht ausgeführt wird, da
ExampleClass.method () Fehler verursacht und die Ausführung nicht fortgesetzt werden kann.
Aber zur Veranschaulichung und zum leichteren Verständnis habe ich diese Reihenfolge beibehalten. ****

Ergebnisse generiert aus chrome developer console& Klicken Sie oben auf den Link jsbin, um den Code zu durchlaufen. Kommentierten Abschnitt mit + umschaltenJS Bin

ctrl/


15

Ja, der erste wird static methodauch genannt class method, während der zweite ein ist instance method.

Betrachten Sie die folgenden Beispiele, um sie genauer zu verstehen.

In ES5

function Person(firstName, lastName) {
   this.firstName = firstName;
   this.lastName = lastName;
}

Person.isPerson = function(obj) {
   return obj.constructor === Person;
}

Person.prototype.sayHi = function() {
   return "Hi " + this.firstName;
}

Im obigen Code isPersonhandelt es sich um eine statische Methode, während sayHies sich um eine Instanzmethode von handelt Person.

Im Folgenden wird beschrieben, wie Sie ein Objekt aus dem PersonKonstruktor erstellen .

var aminu = new Person("Aminu", "Abubakar");

Mit der statischen Methode isPerson.

Person.isPerson(aminu); // will return true

Verwenden der Instanzmethode sayHi.

aminu.sayHi(); // will return "Hi Aminu"

In ES6

class Person {
   constructor(firstName, lastName) {
      this.firstName = firstName;
      this.lastName = lastName;
   }

   static isPerson(obj) {
      return obj.constructor === Person;
   }

   sayHi() {
      return `Hi ${this.firstName}`;
   }
}

Sehen Sie sich an, wie das staticSchlüsselwort zum Deklarieren der statischen Methode verwendet wurde isPerson.

So erstellen Sie ein PersonKlassenobjekt.

const aminu = new Person("Aminu", "Abubakar");

Mit der statischen Methode isPerson.

Person.isPerson(aminu); // will return true

Verwenden der Instanzmethode sayHi.

aminu.sayHi(); // will return "Hi Aminu"

HINWEIS: Beide Beispiele sind im Wesentlichen gleich. JavaScript bleibt eine klassenlose Sprache. Das classin ES6 eingeführte Modell ist in erster Linie ein syntaktischer Zucker gegenüber dem vorhandenen prototypbasierten Vererbungsmodell.


"In ES6" beschreiben Sie nur einen Syntaxzucker. Dies ist nicht die "ES2015" -Methode (bitte jeder hört auf, ES6 zu verwenden, verwenden Sie den richtigen Begriff ES2015). Es ist einfach eine andere Art und meiner Meinung nach die falsche.
K - Die Toxizität in SO nimmt zu.

2
@KarlMorrison Aminu hat nicht "way of do it" geschrieben. Sie haben das einfach selbst geschrieben und eine Ausnahme gemacht. Ihr Standpunkt mag in Bezug auf ES6 und ES2015 fair sein, aber in Gesprächen wird häufig auf eine kürzere Konvention zurückgegriffen, um die Effizienz zu verbessern. Daher halte ich es nicht für möglich oder sicher ratsam, sie aus dem Schreiben zu entfernen.
Wuliwong

Vielen Dank für den ES6-Teil Ihrer Antwort. das verdeutlicht viel, besonders wenn es mit den 2 obigen "öffentlichen + privilegierten" Antworten kombiniert wird. Ich bin aber gründlich von Ihrem verwirrt obj.constructor === PersonSein trueBeispiel wenn ... Whaaaat? Wie kann der Konstruktor einer Klasseninstanz ===die Klasse selbst ...? (Das ist so, als würde man sagen, dass eine Teilmenge einer Menge die Menge selbst ist usw.)
Andrew

Ohhh ... ist das alles, um zu sagen, dass der Konstruktor buchstäblich alles ist, was eine JS-Klasse am Ende des Tages wirklich ist? Alles andere ist entweder im Konstruktor gestapelt oder ein völlig statisches Konstrukt, das von der Klasse isoliert ist, außer nach Name / Konzept (und wie ein implizites "dies", das offensichtlich verfügbar gemacht wird)? (Was ich also für eine Teilmenge der Menge hielt, war eigentlich keine Teilmenge.)
Andrew
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.