2011-04-28 10 views
5

¿Podría proponer alguna solución para implementar una referencia a la variable utilizando cierres o cualquier otro truco?javascript cómo crear la referencia

createReference = function() { 
    // TODO: how to implement? 
}; 

var x = 5; 
var refX = createReference(x); // could be any parameters needed to implement the logic 
x = 6; 
alert(refX()); // should alert 6 

¿Y que pasa contexto como primer argumento y pasar a nombre de la variable (como cadena) y posteriormente evaluar de alguna manera que la referencia en el contexto predefinido. ¿Es esto factible?

He aquí un escenario más completo:

createReference = function(context, prop) { 
    return function() { 
     return context[prop]; 
    }; 
}; 

Provider = function() { 
}; 
Provider.prototype.x = 5; 
Provider.prototype.getXRef = function() { 
    return createReference(this, 'x'); 
}; 
Provider.prototype.incrementX = function() { 
    this.x = this.x + 1; 
}; 

var provider = new Provider(); 
var refX = provider.getXRef(); 
provider.incrementX(); 
alert(refX()); 
+1

En el futuro, no haga sus preguntas como comentarios incrustados en el código. Hace que sea muy difícil ver la pregunta y te arriesgas a que la gente la cierre no es una pregunta. – Oded

+0

Me complace haber respondido su pregunta pero, en su escenario actualizado, ¿por qué no usar simplemente: 'Provider.prototype.getXRef = function() {var that = this; return function() {return that.x; }; }; 'para que pueda evitar el uso de una cadena? – brianpeiris

+0

createReference es una forma universal de hacer un truco. Entonces, en una situación diferente, usaré esta forma universal. En tu comentario: no hay método Provider.prototype.getXRef, pero en algún otro método posiblemente me gustaría pasar referencia a algún otro objeto como un parámetro de devolución de llamada, etc. ... Será más fácil escribir createReference (esto, 'x') luego function() {var that = this; return function() {return that.x; }; }; en el uso diario. –

Respuesta

5

usted tiene que utilizar una cadena del nombre de la variable, pero creo que esto es lo más cerca que nunca obtendrá en JavaScript:

var createReference = function (context, prop) { 
    return function() { return context[prop]; }; 
}; 

var x = 5; 
var refX = createReference(this, 'x'); 
x = 6; 

alert(refX()); // alerts 6 

Editar:

En su escenario actualizado, sería mejor usar un cierre directamente, para que no tenga que usar una cadena del nombre de la variable:

var createReference = function (context, func) { 
    return function() { return func.call(context); } 
}; 

Provider = function() { 
}; 
Provider.prototype.x = 5; 
Provider.prototype.getXRef = function() { 

    return createReference(this, function() { return this.x; }); 

    // OR if you happen to be running in a 
    // JavaScript 1.8 environment like Firefox 3+, 
    // you can use "expression closures" for more 
    // concise code: 

    // return createReference(this, function() this.x); 
}; 
Provider.prototype.incrementX = function() { 
    this.x = this.x + 1; 
}; 

var provider = new Provider(); 
var refX = provider.getXRef(); 
provider.incrementX(); 
alert(refX()); // alerts 6 
+0

Sí, buenas alternativas. Pero Javascript no guarda el tipo de ninguna manera y no habrá errores de "tiempo de compilación" en el uso indebido de los nombres, por lo que creo que es mejor utilizar el enfoque con código más corto y poco legible (a mi favor) a favor del enfoque sin cadenas. –

0

No se puede promover x a ser una referencia.

+0

¿Alguna solución alternativa usando Cierres, etc.? –

2

En JavaScript, no puede pasar valores primitivos (números, cadenas, etc.) por referencia. Sin embargo, cada objeto que pase siempre será por referencia. (Esto incluye matrices)

Para utilizar su ejemplo:

var foo = { x: 5 }; 
var refFoo = foo; 

// foo.x => 5 
// refFoo.x => 5 

foo.x = 6; 

// foo.x => 6 
// refFoo.x => 6 
+0

¿Hay alguna manera de hacer esto con 'new Number (4)'? Ese es un objeto. ¿Puedes (re) establecer su valor para 'mantenerlo vivo' y que se lo pase? Algo como 'n = new Number (4); n2 = n; n2.setValue (7); alerta (n); ' – Rudie

+0

Sí, eso será un objeto. Casi todo en JS es un objeto técnicamente. Sin embargo, los valores escalares (Números, Cadenas, etc.) no se pasan por referencia en absoluto, sino que es exactamente como funciona JS. –

+0

Sé que es un objeto, pero ¿cómo se cambia el valor de un objeto Número? '.setValue' no existe y no puede reasignar un nuevo objeto porque luego pierde la referencia a' n'. No funciona: 'n2 = 7;', 'n2 = new Number (7);', 'n2.setValue (7);'. Los primeros dos pierden referencia, el tercero no existe. ** ¿Cómo cambiar el valor de un objeto numérico? ** – Rudie

0

Solamente los tipos no escalares se pueden pasar como referencia, y siempre pueden pasar como referencia:

var reference = {}; 
my_function(reference); 
console.log(reference); // will show property - a property value 

function my_function(my_reference) { 
    my_reference.property = "a property value"; 
} 

var not_a_reference = []; 
my_function(not_a_reference); 
console.log(not_a_reference); // will NOT show 'a value' 

function my_function() { 
    my_reference.push("a value"); 
} 

Más cerca de su ejemplo:

function show(value) { 
    alert(value.data); 
} 

var value = { 'data': 5 }; 
show(value); // alerts 5 
value.data = 6; 
show(value); // alerts 6 
0

Dado que los objetos serán siempre una referencia estática, se puede hacer esto:

var o = {}; 
o.x = 5; 
var oRef = o; 
alert(oRef.x); // -> 5 
o.x = 6; 
alert(oRef.x); // -> 6 
Cuestiones relacionadas