Respuestas:
La herencia de Javascript se basa en prototipos, por lo que puede extender los prototipos de objetos como Fecha, Matemáticas e incluso sus propios objetos personalizados.
Date.prototype.lol = function() {
alert('hi');
};
( new Date ).lol() // alert message
En el fragmento anterior, defino un método para todos los objetos Date (ya existentes y todos los nuevos).
extend
Por lo general, es una función de alto nivel que copia el prototipo de una nueva subclase que desea extender desde la clase base.
Entonces puedes hacer algo como:
extend( Fighter, Human )
Y el Fighter
constructor / objeto heredará el prototipo de Human
, por lo que si se define como métodos live
y die
el Human
entonces Fighter
también herede esos.
Aclaración actualizada:
"función de alto nivel", que significa .extend, no está integrado, sino que a menudo lo proporciona una biblioteca como jQuery o Prototype.
changing the native objects can break other developer's assumptions of these objects,
conduce a errores de JavaScript que a menudo pueden costar muchas horas rastrear. La oración principal de esta respuesta parece tergiversar esta valiosa práctica de JavaScript.
.extend()
es agregado por muchas bibliotecas de terceros para facilitar la creación de objetos a partir de otros objetos. Consulte http://api.jquery.com/jQuery.extend/ o http://www.prototypejs.org/api/object/extend para ver algunos ejemplos.
.prototype
se refiere a la "plantilla" (si quiere llamarlo así) de un objeto, por lo que al agregar métodos al prototipo de un objeto (lo ve mucho en las bibliotecas para agregar a String, Date, Math o incluso Function) esos métodos se agregan a cada nueva instancia de ese objeto.
El extend
método, por ejemplo, en jQuery o PrototypeJS , copia todas las propiedades del origen al objeto de destino.
Ahora sobre la prototype
propiedad, es un miembro de objetos de función, es parte del núcleo del lenguaje.
Cualquier función se puede utilizar como constructor , para crear nuevas instancias de objeto. Todas las funciones tienen esta prototype
propiedad.
Cuando utiliza el new
operador con en un objeto de función, se creará un nuevo objeto y heredará de su constructor prototype
.
Por ejemplo:
function Foo () {
}
Foo.prototype.bar = true;
var foo = new Foo();
foo.bar; // true
foo instanceof Foo; // true
Foo.prototype.isPrototypeOf(foo); // true
La herencia de Javascript parece ser como un debate abierto en todas partes. Se le puede llamar "El curioso caso del lenguaje Javascript".
La idea es que haya una clase base y luego extienda la clase base para obtener una característica similar a la herencia (no completamente, pero aún así).
La idea es entender qué significa realmente un prototipo. No lo entendí hasta que vi el código de John Resig (cerca de lo que jQuery.extend
hace) escribió un fragmento de código que lo hace y afirma que las bibliotecas base2 y prototipo fueron la fuente de inspiración.
Aquí está el código.
/* 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;
};
})();
Hay tres partes que están haciendo el trabajo. Primero, recorre las propiedades y las agrega a la instancia. Después de eso, crea un constructor para luego agregarlo al objeto. Ahora, las líneas clave son:
// Populate our constructed prototype object
Class.prototype = prototype;
// Enforce the constructor to be what we expect
Class.prototype.constructor = Class;
Primero apunta el Class.prototype
prototipo deseado. Ahora, todo el objeto ha cambiado, lo que significa que debe forzar el diseño a su propio diseño.
Y el ejemplo de uso:
var Car = Class.Extend({
setColor: function(clr){
color = clr;
}
});
var volvo = Car.Extend({
getColor: function () {
return color;
}
});
Lea más sobre esto aquí en Herencia de Javascript por la publicación de John Resig .
Algunas extend
funciones en bibliotecas de terceros son más complejas que otras. Knockout.js, por ejemplo, contiene uno mínimamente simple que no tiene algunas de las comprobaciones que tiene jQuery:
function extend(target, source) {
if (source) {
for(var prop in source) {
if(source.hasOwnProperty(prop)) {
target[prop] = source[prop];
}
}
}
return target;
}
.extends()
crear una clase que es hija de otra clase. Child.prototype.__proto__
establece su valor para Parent.prototype
.prototype
heredar características de uno a otro..__proto__
es un getter / setter para Prototype.
.extend
no está integrado, pero a menudo lo proporciona una biblioteca como jQuery o Prototype.