Parece que Bla2
no lo heredó de la clase Bla
!
Derecha. No ha hecho nada para conectar la herencia, acaba de crear un miembro de Bla2
llamado base
que es una instancia de Bla
. base
no es un identificador especial en JavaScript.
La forma típica de configurar herencia en JavaScript se parece a esto:
// The base constructor function
function Base(x) {
// Base per-instance init
this.x = x;
}
// An example Base function
Base.prototype.foo = function() {
console.log("I'm Base#foo, x = " + this.x);
};
// The Derived constructor function
function Derived(x, y) {
// Normally you need to call `Base` as it may have per-instance
// initialization it needs to do. You need to do it such that
// within the call, `this` refers to the current `this`, so you
// use `Function#call` or `Function#apply` as appropriate.
Base.call(this, x);
// Derived per-instance init
this.y = y;
}
// Make the Derived.prototype be a new object backed up by the
// Base.prototype.
Derived.prototype = Object.create(Base.prototype);
// Fix up the 'constructor' property
Derived.prototype.constructor = Derived;
// Add any Derived functions
Derived.prototype.bar = function() {
console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y);
};
... donde Object.create
es de ES5, pero es una de las cosas que pueden ser fácilmente calzar en su mayoría. (O puede utilizar una función que sólo hace lo mínimo, sin tratar de hacer todo Object.create
, véase más adelante). Y luego lo utiliza:
var d = new Derived(4, 2);
d.foo(); // "I'm Base#foo, x = 4"
d.bar(); // "I'm Derived#bar, x = 4, y = 2"
Live example | source
En código antiguo a veces se ve la Derived.prototype
creó esta forma:
Derived.prototype = new Base();
... pero hay un problema con hacerlo de esa manera: Base
puede hacer la inicialización por instancia que no es apropiado para la totalidad de Derived
heredar. Incluso puede requerir argumentos (como lo hace nuestro Base
; ¿qué pasaríamos por x
?). Al hacer que Derived.prototype
sea un nuevo objeto respaldado por Base.prototype
, obtenemos las cosas correctas. Luego llamamos al Base
desde Derived
para obtener init por instancia.
Lo anterior es muy básico y como puede ver implica una serie de pasos. También hace poco o nada para que las "supercartas" sean fáciles y altamente mantenibles. Es por eso que ve tantos scripts de "herencia", como Prototype's Class
, Dean Edwards 'Base2 o (tos) mi propio Lineage
.
Si no se puede confiar en tener características ES5 en su entorno, y no desea incluir una cuña que hace los fundamentos de Object.create
, sólo puede utilizar esta función en su lugar:
function simpleCreate(proto) {
function Ctor() {
}
ctor.prototype = proto;
return new Ctor();
}
Entonces, en lugar de
Derived.prototype = Object.create(Base.prototype);
que haría:
Derived.prototype = simpleCreate(Base.prototype);
Por supuesto, puede hacer más para automatizar la conexión —, que es todo Lineage
básicamente lo hace.
... y finalmente: Por encima de que he usado para funciones anónimas simplicidad, ej .:
Base.prototype.foo = function() {
// ...
};
... pero yo no hago eso en mi código real, porque I like to help my tools help me. Así que tiendo a usar el patrón de módulo alrededor de cada "clase" (función de constructor y prototipo asociado) y uso la función declaraciones (ya que trabajo para la web, e IE7 e IE8 still have problems con expresiones de funciones nombradas. Así que si no fuera así t usando Lineage
, lo haría por encima de la siguiente manera:
// Base
(function(target) {
// Base constructor
target.Base = Base;
function Base(x) {
// Base per-instance init
this.x = x;
}
// An example Base function
Base.prototype.foo = Base$foo;
function Base$foo() {
console.log("I'm Base#foo, x = " + this.x);
}
})(window);
// Derived
(function(target, base) {
// The Derived constructor function
target.Derived = Derived;
function Derived(x, y) {
// Init base
base.call(this, x);
// Derived per-instance init
this.y = y;
}
// Make the Derived.prototype be a new object backed up by the
// Base.prototype.
Derived.prototype = Object.create(base.prototype);
// Fix up the 'constructor' property
Derived.prototype.constructor = Derived;
// Add any Derived functions
Derived.prototype.bar = Derived$bar;
function Derived$bar() {
console.log("I'm Derived#bar, x = " + this.x + ", y = " + this.y);
}
})(window, Base);
... o algo por el estilo Live copy | source
Está sucediendo porque nada en su código se encarga de que * no * a suceder.. Si estás pensando que configurar una propiedad llamada "base" hace que una clase herede de otra, bueno, eso es incorrecto. – Pointy
Gracias por el formato, @MarkLinus! – corazza
Intenta configurar 'Bla2.prototype' a' new Bla() '. – Pointy