var User = {
    Name: "Some Name", Age: 26,
    Show: function() { alert("Age= "+this.Age)}; 
};

function Test(fn) {
    fn();         
}

Test(User.Show);

===============

La alerta que se muestra por código es "Edad = Indefinida". Entiendo que la función User.Show se llama desde el interior de Test (), se refiere a 'this' de la función 'Test ()' en lugar del objeto 'User'. Mi pregunta es si hay alguna forma de resolver este problema.

3
Praveen Prasad 25 nov. 2009 a las 21:10

5 respuestas

La mejor respuesta

La forma de resolver este problema es pasar el objeto al que está apuntando "esto", dentro de la función Prueba ...

function Test(fn, scope, args) {
    fn.apply(scope, args);
}

Test(User.Show, User, []);

Donde la matriz args le permite pasar adicionalmente cualquier argumento que pueda tener. También puede dejar la función Prueba tal como está y simplemente pasar una función anónima ...

Test(function() {User.Show()});
7
Roatin Marth 25 nov. 2009 a las 18:51

Otra forma de usar call()

var User = {
    Name: "Some Name", 
    Age: 26,
    Show: function() { alert("Age= "+this.Age);} 
};

function Test(fn,obj) {
    fn.call(obj);         
}

Test(User.Show, User);

Puede encontrar interesante la presentación de Aprendizaje avanzado de JavaScript de John Resig, especialmente interesante la sección sobre contexto

1
Russ Cam 25 nov. 2009 a las 21:03

Tienes 2 errores. Primero, su punto y coma debe moverse dentro del}, pero el código debe ser function() { alert("Age= "+User.Age);} si desea llamarlo como está y hacer que muestre la edad.

1
Jarrett Widman 25 nov. 2009 a las 18:24

También puedes hacer esto:

Test(User.Show.bind(User));

Teniendo en cuenta que para usar las otras sugerencias, aún tendría que pasar el alcance como parámetro, como:

function Test(fn, scope) {
    fn.apply(scope || window);
}

Test(User.Show, User)

La alternativa parece razonable y más fácil.

Además, este artículo le puede interesar:

Alcance en JavaScript

Explica el tipo de problema que enfrenta, así como las formas de solucionarlo.
Mucho mejor que cualquier cosa que pueda escribir aquí como respuesta :)

2
Carlos Lima 25 nov. 2009 a las 20:10

Una forma de hacer que se ejecute en el ámbito de User es pasar su función Test a un ámbito.

function Test(fn, scope) {
    fn.apply(scope || window);
}

Esto aplicará la función pasada al alcance o ventana pasada si no se pasó ningún alcance.

Test(User.Show, User) alertaría a Age= 26.

5
Jordan S. Jones 25 nov. 2009 a las 19:03