Artur Sapek
Artur Sapek

Reputation: 2497

Anonymous function losing scope

Why is this not working?

var img = new Image();
this.dimensions = [ ];
var m = this;
img.onload = function(){ 
    return function(){
        m.dimensions = [ this.width, this.height ]; 
    }
};
img.src = 'images/whatever.jpg';


console.log(this.dimensions);
[]

(inside of a JS object, hence the "this")

EDIT: working code

var img = new Image();
this.dimensions = [  ];
var m = this;
img.onload = function(){ 
    m.dimensions.push(this.width, this.height);  
    console.log(m.dimensions) // had to wait
};
img.src = 'whatever.jpg';

Upvotes: 0

Views: 549

Answers (3)

Skyd
Skyd

Reputation: 421

Are you sure console.log(this.dimensions) is being run AFTER the image has loaded? What you've added to img.onload is a callback function to run after the image has finished loading in DOM. Until that img has finished loading, m.dimensions will not be set yet. The image does not load immediately when you add the callback, but loads asynchronously and can finish whenever.

In other words, you are running console.log(this.dimensions) before the dimensions has been set yet (before the onload callback is run). I bet if you wrapped the console.log inside a setTimeout call with say 5 seconds, then it would log what you expected.

Upvotes: 1

user166390
user166390

Reputation:

Consider that this code won't alert:

img.onload = function(){ 
    return function(){
        alert("hi")
    }
};

Then consider the standard (likely desired) "double-closure":

img.onload = (function(m){ 
    return function(){
        alert(m)
    }
})(this)

Happy coding.

Upvotes: 1

Ben Lee
Ben Lee

Reputation: 53329

That's because this changes meaning inside new function definitions. You solve this by caching this in a local variable. Here, that's already done; your saving it in the variable m. So just use m instead of this.

var img = new Image();
this.dimensions = [ ];
var m = this;
img.onload = function(){ 
    return function(){
        m.dimensions = [ m.width, m.height ]; 
    }
};
img.src = 'images/whatever.jpg';

Here's a good tutorial explaining how this changes meaning in different contexts: http://javascriptweblog.wordpress.com/2010/08/30/understanding-javascripts-this/

Upvotes: 1

Related Questions