Su código está en el orden en que lo citó, ¿no es así? ¿El singleton aparece sobre el RequestManager
en la fuente?
Si es así, ese es su problema. (!) Es bastante sutil, pero asumiendo sus dos bits de código indicadas son en el orden en que se ha mostrado, aquí está el orden en el que las cosas suceden (lo explicaré más adelante):
- La función
RequestManager
se define.
- Su función anónima que crea las ejecuciones de singleton, incluida la instancia de una instancia de
RequestManager
.
- El prototipo
RequestManager
se reemplaza por uno nuevo.
Dado que la instancia se crea una instancia myRequestManager
antes se cambió el prototipo, que no tiene las funciones que ha definido en ese (nuevo) prototipo. Continúa utilizando el objeto prototipo que estaba en su lugar cuando se creó una instancia.
Puedes solucionar este problema fácilmente reordenando el código, o añadiendo propiedades a RequestManager
's prototipo en lugar de reemplazarlo, por ejemplo:
RequestManager.prototype.require = function(text){
//make an ajax request
};
RequestManager.prototype.otherFunc = function(){
//do other things
};
que funciona porque tiene no sustituyen la objeto prototipo, que acaba de agregar. myRequestManager
ve las adiciones porque las ha agregado al objeto que está usando (en lugar de establecer un nuevo objeto en la propiedad prototype
de la función del constructor).
Por qué esto sucede es un poco técnico y voy a ceder a la especificación. Cuando el intérprete ingresa a un nuevo "contexto de ejecución" (por ejemplo, una función, o el — global, por ejemplo, contexto de página —), el orden en el que hace las cosas no es estricto orden de origen descendente, hay fases . Una de las primeras fases es crear una instancia de todas las funciones definidas en el contexto; sucede antes de se ejecuta cualquier código paso a paso. Detalles en todo su esplendor en las secciones 10.4.1 (código global), 10.4.3 (código de función) y 10.5 (enlaces de declaración) en the spec, pero básicamente, las funciones se crean antes de la primera línea del código paso a paso.:-)
Esto es más fácil de ver con un ejemplo aislado de prueba:
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8">
<title>Test Page</title>
<style type='text/css'>
body {
font-family: sans-serif;
}
</style>
<script type='text/javascript'>
// Uses Thing1
var User1 = (function() {
var thing1 = new Thing1();
function useIt() {
alert(thing1.foo());
}
return useIt;
})();
// Uses Thing2
var User2 = (function() {
var thing2 = new Thing2();
function useIt() {
alert(thing2.foo());
}
return useIt;
})();
// Thing1 gets its prototype *replaced*
function Thing1() {
this.name = "Thing1";
}
Thing1.prototype = {
foo: function() {
return this.name;
}
};
// Thing2 gets its prototype *augmented*
function Thing2() {
this.name = "Thing2";
}
Thing2.prototype.foo = function() {
return this.name;
};
// Set up to use them
window.onload = function() {
document.getElementById('btnGo').onclick = go;
}
// Test!
function go() {
alert("About to use User1");
try
{
User1();
}
catch (e)
{
alert("Error with User1: " + (e.message ? e.message : String(e)));
}
alert("About to use User2");
try
{
User2();
}
catch (e)
{
alert("Error with User2: " + (e.message ? e.message : String(e)));
}
}
</script>
</head>
<body><div>
<div id='log'></div>
<input type='button' id='btnGo' value='Go'>
</div></body>
</html>
Como se puede ver si se ejecuta, User1
falla porque el Thing1
instancia que está usando no tiene una propiedad foo
(porque el prototipo fue reemplazado), pero User2
funciona porque la instancia Thing2
usa * does (porque el prototipo fue aumentado, no reemplazado).
No recibí el error ... ¿De dónde viene 'params' cuando construye el RequestManager? –
En la muestra de código que proporciona, params no está definido en ninguna parte. ¿Dejaste algo fuera de tu ejemplo? – Robusto