2010-06-24 13 views
9

estoy corriendo en el problema siguiente que ha realmente me tiene perplejo:llamando a la función miembro de Javascript constructor

tengo

function SystemList(UID) 
{ 
    this.refreshData(); 
} 

SystemList.prototype.refreshData = function() 
{ 
    this.systemDataObj({}, $.proxy(this.readSuccess, this)); 
} 

Cuando intento y funciono esto, me sale el siguiente error: no detectada TypeError: Object # no tiene el método 'refreshData' dentro del constructor.

¿Alguien tiene una idea de por qué esto está fallando? En mi opinión, parece que debería estar funcionando.

Editar:

Ejemplo de cómo creo una instancia:

function UserMiniProfile(UID) 
{ 
    this.UID = UID; 
    this.systemList = new SystemList(this.UID); 
    this.htmlID = 'user-'+this.UID+'-profile'; 
} 
+0

Agregué un ejemplo de cómo creo el obj. – nazbot

+1

¿Estás seguro de que estás usando el constructor 'SystemList' * después de * aumentar su prototipo? – CMS

+0

funciona para mí: http://jsbin.com/ebasa/edit – nickf

Respuesta

13

Creo que probablemente está ejecutando en el tema de cómo y cuándo se producen las declaraciones de función frente al código paso a paso (lo que llama la especificación código de instrucción).

código como éste fallará en la forma en que usted describe, por ejemplo:

var obj = new Thingy("Fred"); 

function Thingy(name) { 
    this.setName(name); 
} 

Thingy.prototype.setName = function(name) { 
    this.name = name; 
}; 

... porque usted está llamando al constructor antes de añadir la función setName al prototipo. Tenga en cuenta que llamar al constructor antes de su declaración está bien, es solo porque el constructor está usando una función que está configurada más tarde por el código de la declaración de que hay un problema. El orden en el que el intérprete de JavaScript tratará de procesar que el código es:

  1. crear la función Thingy y ponerla a disposición de la mira telescópica.
  2. Ejecute la línea var obj = ...., llamando al constructor.
  3. Ejecute el código del constructor (que en este caso arroja una excepción porque no hay una función this.setName).
  4. Ejecute la línea Thingy.prototype.setName = .... (Si no se ha lanzado ninguna excepción en el último paso, es decir)

Estos pasos ocurren para cada bloque de scripts (primero se realizan las declaraciones de función, luego se ejecuta el código de instrucción en orden), y aunque el ejemplo anterior es bastante obvio, cuando comienzas a juntar piezas de diferentes ubicaciones, puedes crear esta situación de forma menos obvia.

La solución, por supuesto, es asegurarse de que usted no está construyendo el objeto antes de que haya configurado la propiedad setName:

function Thingy(name) { 
    this.setName(name); 
} 

Thingy.prototype.setName = function(name) { 
    this.name = name; 
}; 

var obj = new Thingy("Fred"); 

... y otra vez, lo anterior es bastante obvio, pero es posible crear estas situaciones de forma menos obvia en el mundo real.

Mi sospecha es que esto es lo que está sucediendo en su caso. Es fácil de probar: utilizar un depurador como Firebug en Firefox, VS.Net o el Script Debugger para IE, DevTools de Chrome, etc., ponga un punto de interrupción en la línea SystemList.prototype.refreshData = ... y un punto de interrupción en la línea donde está haciendo su new SystemList(...) y vea cuál se ejecuta primero.

Aquí hay un par de violines que demuestran el problema: This one falla en el constructor, this one tiene éxito.

+0

Disculpe la demora, sí, este fue el problema. Moví las cosas y funciona ahora. – nazbot

+0

@nazbot: ¡Ah, bien, me alegro de que haya sido eso! –

0

Es necesario asignar su primera clase:

SystemList = function(UID) 
{ 
    this.refreshData(); 
} 

SystemList.prototype.refreshData = function() 
{ 
    this.systemDataObj({}, $.proxy(this.readSuccess, this)); 
} 
+0

¿De verdad? Nunca he visto esta forma de especificar una clase js. – nazbot

+2

No, cambiarlo de 'función SystemList (UID)' a 'SystemList = function (UID)' no tiene nada que ver con eso. Todo lo que hace es cambiarlo de una función nombrada a una función anónima. –

+3

(Citando a mí) * "Todo lo que hace es cambiarlo de una función nombrada a una anónima". * En realidad, eso no es * todo *. También lo cambia de una función * declaración * a una función * expresión *, que ocurrirá más tarde. Si estoy en lo cierto sobre lo que está sucediendo con el código OP, el resultado probable de este cambio sería que en lugar de que el constructor fallara, la * llamada * al constructor fallaría porque 'SystemList' no estaría definida. No resuelve el problema de ninguna manera, pero mi declaración anterior estaba incompleta, así que pensé que debería señalarlo. –

Cuestiones relacionadas