JavaScript: Wofür werden .extend und .prototype verwendet?

122

Ich bin relativ neu in JavaScript und sehe immer wieder .extend und .prototype in Bibliotheken von Drittanbietern, die ich verwende. Ich dachte, es hätte mit der Prototype-Javascript-Bibliothek zu tun, aber ich fange an zu denken, dass dies nicht der Fall ist. Wofür werden diese verwendet?

Andrew
quelle

Antworten:

136

Die Vererbung von Javascript basiert auf Prototypen, sodass Sie die Prototypen von Objekten wie Datum, Mathematik und sogar Ihren eigenen benutzerdefinierten Objekten erweitern können.

Date.prototype.lol = function() {
 alert('hi');
};

( new Date ).lol() // alert message

Im obigen Snippet definiere ich eine Methode für alle Datumsobjekte (bereits vorhandene und alle neuen).

extend ist normalerweise eine übergeordnete Funktion, die den Prototyp einer neuen Unterklasse kopiert, die Sie aus der Basisklasse erweitern möchten.

Sie können also Folgendes tun:

extend( Fighter, Human )

Und der FighterKonstruktor / Objekt wird den Prototyp erben Human, wenn Sie also Methoden definieren, wie liveund dieauf Humandann Fighterwerden auch diejenigen erben.

Aktualisierte Klarstellung:

"High-Level-Funktion" bedeutet, dass .extend nicht integriert ist, sondern häufig von einer Bibliothek wie jQuery oder Prototype bereitgestellt wird.

meder omuraliev
quelle
75
Die Bedeutung "Funktion auf hoher Ebene" .extendist nicht integriert, wird jedoch häufig von einer Bibliothek wie jQuery oder Prototype bereitgestellt.
Visum
13
Ich würde hinzufügen, dass es nicht empfohlen wird, die Prototypen von nativen Objekten in JS zu erweitern
Framp
1
@meder - Sie sollten Ihrer Antwort einen Visum-Kommentar hinzufügen. :)
Manish Gupta
9
In der modernen Javascript-Programmierung ist es üblich, Globale und native Objekte wie Elemente eines öffentlichen Badezimmers zu behandeln. Sie können es nicht vermeiden, dort hineinzugehen, aber Sie sollten versuchen, den Kontakt mit Oberflächen zu minimieren. Dies liegt daran, changing the native objects can break other developer's assumptions of these objects,dass es zu Javascript-Fehlern kommt, deren Aufspüren oft viele Stunden kosten kann. Der führende Satz zu dieser Antwort scheint diese wertvolle Javascript-Praxis falsch darzustellen.
Ninjaxor
24

.extend()wird von vielen Bibliotheken von Drittanbietern hinzugefügt, um das Erstellen von Objekten aus anderen Objekten zu vereinfachen. Einige Beispiele finden Sie unter http://api.jquery.com/jQuery.extend/ oder http://www.prototypejs.org/api/object/extend .

.prototype bezieht sich auf die "Vorlage" (wenn Sie es so nennen möchten) eines Objekts. Wenn Sie also dem Prototyp eines Objekts Methoden hinzufügen (dies wird häufig in Bibliotheken angezeigt, um diese Methoden zu String, Date, Math oder sogar Function hinzuzufügen) werden zu jeder neuen Instanz dieses Objekts hinzugefügt.

pnomolos
quelle
19

Die extendMethode, beispielsweise in jQuery oder PrototypeJS , kopiert alle Eigenschaften von der Quelle in das Zielobjekt.

Was nun die prototypeEigenschaft betrifft, so ist sie Mitglied von Funktionsobjekten und Teil des Sprachkerns.

Jede Funktion kann als Konstruktor verwendet werden , um neue Objektinstanzen zu erstellen. Alle Funktionen haben diese prototypeEigenschaft.

Wenn Sie den newOperator mit für ein Funktionsobjekt verwenden, wird ein neues Objekt erstellt und von seinem Konstruktor geerbt prototype.

Beispielsweise:

function Foo () {
}
Foo.prototype.bar = true;

var foo = new Foo();

foo.bar; // true
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
CMS
quelle
18

Die Vererbung von Javascript scheint überall wie eine offene Debatte zu sein. Es kann "Der merkwürdige Fall der Javascript-Sprache" genannt werden.

Die Idee ist, dass es eine Basisklasse gibt und Sie dann die Basisklasse erweitern, um eine vererbungsähnliche Funktion zu erhalten (nicht vollständig, aber immer noch).

Die ganze Idee ist zu verstehen, was Prototyp wirklich bedeutet. Ich habe es nicht bekommen, bis ich gesehen habe, dass John Resigs Code (in der Nähe dessen, was er jQuery.extendtut) einen Codeblock geschrieben hat, der dies tut, und er behauptet, dass Base2- und Prototyp-Bibliotheken die Quelle der Inspiration waren.

Hier ist der Code.

    /* Simple JavaScript Inheritance
     * By John Resig http://ejohn.org/
     * MIT Licensed.
     */  
     // Inspired by base2 and Prototype
    (function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};

  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;

    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;

    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;

            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];

            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);        
            this._super = tmp;

            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }

    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }

    // Populate our constructed prototype object
    Class.prototype = prototype;

    // Enforce the constructor to be what we expect
    Class.prototype.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;

    return Class;
  };
})();

Es gibt drei Teile, die den Job machen. Zunächst durchlaufen Sie die Eigenschaften und fügen sie der Instanz hinzu. Danach erstellen Sie einen Konstruktor, der später zum Objekt hinzugefügt werden soll. Jetzt lauten die wichtigsten Zeilen:

// Populate our constructed prototype object
Class.prototype = prototype;

// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;

Sie zeigen zuerst Class.prototypeauf den gewünschten Prototyp. Jetzt hat sich das gesamte Objekt geändert, sodass Sie das Layout auf das eigene zurücksetzen müssen.

Und das Anwendungsbeispiel:

var Car = Class.Extend({
  setColor: function(clr){
    color = clr;
  }
});

var volvo = Car.Extend({
   getColor: function () {
      return color;
   }
});

Lesen Sie mehr darüber hier bei Javascript Inheritance von John Resigs Beitrag.

ambodi
quelle
2

Einige extendFunktionen in Bibliotheken von Drittanbietern sind komplexer als andere. Knockout.js enthält beispielsweise eine minimal einfache Datei, die einige der von jQuery's durchgeführten Überprüfungen nicht enthält:

function extend(target, source) {
    if (source) {
        for(var prop in source) {
            if(source.hasOwnProperty(prop)) {
                target[prop] = source[prop];
            }
        }
    }
    return target;
}
Simon_Weaver
quelle
2
  • .extends() Erstellen Sie eine Klasse, die ein Kind einer anderen Klasse ist.
    hinter den Kulissen Child.prototype.__proto__setzt seinen Wert auf, Parent.prototype
    damit Methoden vererbt werden.
  • .prototype Features von einem zum anderen erben.
  • .__proto__ ist ein Getter / Setter für Prototype.
humaid
quelle
Sollte dies nicht .extend () und nicht .extends () sein?
SJHowe