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
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.
.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.
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
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.
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;
}
"la funzione di alto livello", che significa '.extend' non è built-in, ma spesso fornita da una libreria di tale come jQuery o Prototype. – visum
Vorrei aggiungere che non è consigliabile estendere i prototipi di oggetti nativi in JS – framp
@meder - è necessario aggiungere commenti visum nella risposta. :) –