2010-09-23 13 views
111

Sono relativamente nuovo in JavaScript e continuo a vedere .extend e .prototype nelle librerie di terze parti che sto utilizzando. Pensavo che avesse a che fare con la libreria javascript di Prototype, ma sto cominciando a pensare che non sia così. Per cosa sono usati?JavaScript: a cosa servono .extend e .prototype?

risposta

119

L'ereditarietà di Javascript è basata su prototipi, quindi estendi i prototipi di oggetti come Data, Matematica e persino i tuoi personalizzati.

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

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

Nel frammento di sopra, mi definiscono un metodo per tutti oggetti Date (quelli già esistenti e tutti quelli nuovi).

extend è in genere una funzione di alto livello che copia il prototipo di una nuova sottoclasse che si desidera estendere dalla classe base.

Così si può fare qualcosa di simile:

extend(Fighter, Human) 

E il Fighter costruttore/oggetto erediterà il prototipo di Human, quindi se si definisce metodi come live e die su Human poi Fighter erediterà anche quelli.

Chiarimento Aggiornato:

"la funzione di alto livello", che significa .extend non è built-in, ma spesso fornita da una libreria, come jQuery o Prototype.

+69

"la funzione di alto livello", che significa '.extend' non è built-in, ma spesso fornita da una libreria di tale come jQuery o Prototype. – visum

+13

Vorrei aggiungere che non è consigliabile estendere i prototipi di oggetti nativi in ​​JS – framp

+1

@meder - è necessario aggiungere commenti visum nella risposta. :) –

22

.extend() viene aggiunto da molte librerie di terze parti per semplificare la creazione di oggetti da altri oggetti. Vedere http://api.jquery.com/jQuery.extend/ o http://www.prototypejs.org/api/object/extend per alcuni esempi.

.prototype si riferisce al "modello" (se si desidera chiamarlo così) di un oggetto, quindi aggiungendo metodi al prototipo di un oggetto (lo si vede molto nelle librerie da aggiungere a String, Date, Math o Even Function) quei metodi vengono aggiunti ad ogni nuova istanza di quell'oggetto.

18

Il metodo extend ad esempio in jQuery o PrototypeJS, copia tutte le proprietà dall'origine all'oggetto di destinazione.

Ora circa la proprietà prototype, è un membro di oggetti funzione, fa parte del nucleo linguistico.

Qualsiasi funzione può essere utilizzata come constructor, per creare nuove istanze di oggetto. Tutte le funzioni hanno questa proprietà prototype.

Quando si utilizza l'operatore new su un oggetto funzione, verrà creato un nuovo oggetto che erediterà dal suo costruttore prototype.

Ad esempio:

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

var foo = new Foo(); 

foo.bar; // true 
foo instanceof Foo; // true 
Foo.prototype.isPrototypeOf(foo); // true 
16

Javascript eredità sembra essere come un dibattito aperto in tutto il mondo. Può essere chiamato "Il curioso caso del linguaggio Javascript".

L'idea è che esiste una classe base e quindi si estende la classe base per ottenere una funzione di tipo ereditario (non completamente, ma ancora).

L'idea è quella di ottenere ciò che significa realmente il prototipo. Non l'ho capito fino a quando non ho visto il codice di John Resig (vicino a ciò che fa jQuery.extend) che ha scritto un chunk di codice che lo fa e sostiene che le basi2 e le librerie di prototipi erano la fonte di ispirazione.

Ecco il codice.

/* 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; 
    }; 
})(); 

Ci sono tre parti che stanno facendo il lavoro. Per prima cosa, esegui il loop delle proprietà e aggiungili all'istanza. Dopo di che, si crea un costruttore per poi essere aggiunti al object.Now, le linee principali sono:

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

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

È il primo punto Class.prototype al prototipo desiderato. Ora, l'intero oggetto è cambiato nel senso che è necessario forzare il layout di nuovo al proprio.

E l'esempio di utilizzo:

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

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

leggere di più qui a Javascript Inheritance by John Resig s' posta.

1

Alcune funzioni di extend nelle librerie di terze parti sono più complesse di altre. Knockout.js per esempio contiene una minima semplice che non ha alcuni dei controlli che jQuery di fa:

function extend(target, source) { 
    if (source) { 
     for(var prop in source) { 
      if(source.hasOwnProperty(prop)) { 
       target[prop] = source[prop]; 
      } 
     } 
    } 
    return target; 
} 
Problemi correlati