views:

114

answers:

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

function Test(fn) {
    fn();         
}

Test(User.Show);

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

Alert shown by code is "Age= Undefined". I understand as User.Show function is called from inside of Test(), refers 'this' of 'Test()' function rather than 'User' object. My question is if there is any way to solve this problem?

+3  A: 

One way to get it to execute on the scope of User is to pass your Test function a scope.

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

This will apply the passed function to the passed scope, or window if no scope was passed.

Test(User.Show, User) would alert Age= 26.

Jordan S. Jones
+1  A: 

You have 2 mistakes. 1st is your semicolon should be moved inside of the } but the code should be function() { alert("Age= "+User.Age);} if you want to call it the way you are and have it show the age.

jarrett
semicolon is just a typos mistake, what jordan s jones is saying is actually the thing iam looking for, or may be something more better.
Praveen Prasad
+4  A: 

The way to solve this problem is to pass in the object you're scoping "this" to, inside of the Test function...

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

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

Where the args array allows you to additionally pass in any arguments you may have. You could also leave the Test function as it is and just pass in an anonymous function...

Test(function() {User.Show()});
MillsJROSS
Right. In JavaScript, per ECMA standard, `user.show` is just the function `show`. What you want is a new function that remembers that `user` is the `this` object to use.
Jason Orendorff
+1  A: 

You could also do this:

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

Considering that to use the other suggestions you'd still have to pass the scope as the parameter, like:

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

Test(User.Show, User)

The alternative seems reasonable and easier.

Also, you might find this article interesting:

Scope in JavaScript

It explains the kind of issue you're facing as well as ways to get around it.
Much better than anything I could possibly write here as an answer :)

Carlos Lima
Uh, no you can't. Not in all browsers at least.
Roatin Marth
Fair point. :-(
Carlos Lima
A: 
var User = {
    Name: "Some Name", 
    Age: 26,
    Show: function() { alert("Age= "+User.Age)}
};

function Test(fn) {
    fn();
}
Test(User.Show);

ps! refers 'this' of 'Test()' function rather than 'User'

No - in fact 'this' points to the window-object

Terje
A: 

Another way using 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);

You may find John Resig's Learning Advanced JavaScript slideshow interesting, particularly the section on context

Russ Cam