2012-01-02 11 views
6

Soy un novato en el mundo de JavaScript, y se me ocurrió este extraño problema cuando intentaba un prototipo de herencia de encadenamiento.Javascript Prototype Chaining super class constructor and method calling

tengo 3 clases

//class parent 
function parent(param_1){ 
    this.param = param_1; 
    this.getObjWithParam = function(val){ 
     console.log("value in parent class "+val); 
     console.log("Constructor parameter : "+this.param); 
    }; 

}; 

//class child 
function child(param_1){ 
    this.constructor(param_1); 
    this.getObjWithParam = function(val){ 
     console.log("value in child class "+val); 
     val = Number(val)+1; 
     child.prototype.getObjWithParam.call(this, [val]); 
    }; 
}; 
child.prototype = new parent(); 

//class grandChild 
function grandChild(param_1){ 
    this.constructor(param_1); 
}; 
grandChild.prototype = new child(); 


var gc = new grandChild(666); 
gc.getObjWithParam(0); 

En primer lugar, quería pasar un parámetro al constructor de las clases padre, al igual que la forma de hacer llamando a super (args) en otros lenguajes orientados a objetos. así que this.constructor(param_1); se adapta a la finalidad.

Sin embargo, la salida aparece como

value in parent class 0 
Constructor parameter : 666 

Lo que sugiere, que el nieto de clases ha saltado la cadena de prototipo, y en lugar de llamar getObjWithParam() del niño() de clase, ha llamado getObjWithParam() de la clase de padres

¿Alguien tiene alguna idea de lo que sale mal aquí?

NB: 2 hallazgos más quiero agregar, y el segundo es el más importante. -> Si trato de encontrar el constructor de la clase nieto por

console.log(gc.constructor) 

la salida me sale es

function parent(param_1){ 
    this.param = param_1; 
    this.getObjWithParam = function(val){ 
     console.log("value in parent class "+val); 
     console.log("Constructor parameter : "+this.param); 
    }; 
} 

que es el no del todo lo que esperaba. Esperaba ver la clase infantil.

-> Si trato de comentario//this.constructor(param_1); en el niño() y la clase Nieto(), el código funciona exactamente como se esperaba.

¿Alguien podría explicar este fenómeno por favor?

Además, será muy apreciado si alguien pudiera sugerir una solución alternativa.

Gracias

Respuesta

4

Declarar una this.SOME_METHOD en la función constructora no añadirlo a el prototipo del tipo. prototipo funciona necesitan ser declarados por separado, por ejemplo .:

//class parent 
function parent(param_1){ 
    console.log("parent " + param_1); 
    this.param = param_1; 
} 

parent.prototype.getObjWithParam = function(val) { 
    console.log("value in parent class "+val); 
    console.log("Constructor parameter : "+this.param); 
}; 

//class child 
function child(param_1){ 
    console.log("child " + param_1); 
    this.constructor(param_1); 
} 
child.prototype = new parent(); 
child.prototype.getObjWithParam = function(val) { 
    console.log("value in child class "+val); 
    val = Number(val)+1; 
    parent.prototype.getObjWithParam.call(this, [val]);  
} 

//class grandChild 
function grandChild(param_1){ 
    console.log("grandChild " + param_1); 
    this.constructor(param_1); 
} 
grandChild.prototype = new child(); 


var gc = new grandChild(666); 
gc.getObjWithParam(0); 

recomendaría a leer this article, para obtener una visión más profunda de cómo funcionan los prototipos en javascript.

+0

Su ejemplo y el artículo fueron de ayuda, sin embargo, supongo que esto me lleva de vuelta al principio. Estaba intentando llamar a los métodos de superclase en prototipo de herencia de encadenamiento. Intenté llamar al método constructor de la clase superior usando 'this.constructor (param_1); ' e intentado llamar al método de superclase por' Class.prototype.function.call (this, [param]); ' Así que supongo que llamaré al método de superclase como estaba haciendo, y deja de usar '//this.constructor (param_1);' En su lugar, tendré algún método en la clase padre para inicializar las variables heredadas, a las que puedo llamar desde la clase hija. – Tirtha

3

Si usted quiere hacer el encadenamiento (Fluent Interface) como en jQuery:

<div id="div"></div> 

<script type="text/javascript"> 
function $(id) { 
    if(this.$) return new $.init(id); 
} 

$.init = function(id) { 
    if(typeof id == 'string') { 
     this.id = document.getElementById(id); 
    } 
}; 

$.init.prototype = $.prototype = { 
    constructor: $, 
    css: function(value) { 
     for(i in value) { 
      this.id.style[i] = value[i]; 
     } 
     return this; 
    }, 
    mush : function() { 
     var text = this.id.innerHTML; 
     this.id.innerHTML = text.split('').join('--'); 
     return this; 
    }, 
    text : function(a) { 
     this.id.innerHTML = a; 
     return this; 
    } 
}; 

$('div').text('FOO').mush().css({ 
     'color' : 'red', 
     'textTransform' : 'uppercase' 
}); 
</script> 

Ver example

Cuestiones relacionadas