Risposte:
L'ereditarietà di Javascript è basata su prototipi, quindi estendi i prototipi di oggetti come Date, Math e persino quelli personalizzati.
Date.prototype.lol = function() {
alert('hi');
};
( new Date ).lol() // alert message
Nello snippet sopra, definisco un metodo per tutti gli oggetti Date (quelli già esistenti e tutti quelli nuovi).
extend
è solitamente una funzione di alto livello che copia il prototipo di una nuova sottoclasse che si desidera estendere dalla classe base.
Quindi puoi fare qualcosa come:
extend( Fighter, Human )
E il Fighter
costruttore / oggetto erediterà il prototipo di Human
, quindi se si definisce metodi come live
e die
in Human
poi Fighter
sarà anche ereditare quelli.
Chiarimento aggiornato:
"funzione di alto livello" che significa .extend non è integrato ma spesso fornito da una libreria come jQuery o Prototype.
changing the native objects can break other developer's assumptions of these objects,
porta a bug di javascript che spesso possono costare molte ore per rintracciarli. La frase principale di questa risposta sembra travisare questa preziosa pratica di javascript.
.extend()
viene aggiunto da molte librerie di terze parti per semplificare la creazione di oggetti da altri oggetti. Vedi http://api.jquery.com/jQuery.extend/ o http://www.prototypejs.org/api/object/extend per alcuni esempi.
.prototype
si riferisce al "modello" (se vuoi chiamarlo così) di un oggetto, quindi aggiungendo metodi al prototipo di un oggetto (lo vedi spesso nelle librerie da aggiungere a String, Date, Math o anche Function) quei metodi vengono aggiunti a ogni nuova istanza di quell'oggetto.
Il extend
metodo, ad esempio in jQuery o PrototypeJS , copia tutte le proprietà dall'origine all'oggetto di destinazione.
Ora riguardo alla prototype
proprietà, è un membro degli oggetti funzione, fa parte del nucleo del linguaggio.
Qualsiasi funzione può essere utilizzata come costruttore per creare nuove istanze di oggetti. Tutte le funzioni hanno questa prototype
proprietà.
Quando usi l' new
operatore con su un oggetto funzione, verrà creato un nuovo oggetto, che erediterà dal suo costruttore prototype
.
Per esempio:
function Foo () {
}
Foo.prototype.bar = true;
var foo = new Foo();
foo.bar; // true
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
L'ereditarietà di Javascript sembra essere come un dibattito aperto ovunque. Può essere chiamato "Il curioso caso del linguaggio Javascript".
L'idea è che esista una classe base e quindi estendi la classe base per ottenere una caratteristica simile all'ereditarietà (non completamente, ma comunque).
L'idea è di capire cosa significa veramente prototipo. Non l'ho capito fino a quando non ho visto il codice di John Resig (vicino a quello che jQuery.extend
fa) ha scritto un blocco di codice che lo fa e afferma che le librerie base2 e prototipo 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. Innanzitutto, scorri le proprietà e le aggiungi all'istanza. Dopodiché, crei un costruttore da aggiungere in seguito all'oggetto, ora le linee chiave sono:
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
Per prima cosa punti il Class.prototype
prototipo desiderato. Ora, l'intero oggetto è cambiato, il che significa 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;
}
});
Per saperne di più qui su Javascript Inheritance dal post di John Resig .
Alcune extend
funzioni nelle librerie di terze parti sono più complesse di altre. Knockout.js, ad esempio, ne contiene uno minimamente semplice che non ha alcuni dei controlli che fa jQuery:
function extend(target, source) {
if (source) {
for(var prop in source) {
if(source.hasOwnProperty(prop)) {
target[prop] = source[prop];
}
}
}
return target;
}
.extends()
creare una classe che sia figlia di un'altra classe. Child.prototype.__proto__
imposta il suo valore in Parent.prototype
.prototype
ereditano le caratteristiche l'una dall'altra..__proto__
è un getter / setter per Prototype.
.extend
non è integrato ma spesso fornito da una libreria come jQuery o Prototype.