1

I'm trying to access an object's members from within an event function. Sorry if I'm doing things wrong, I'm a beginner :)

I have something like this:

function MyObject( canvas )
{
    this.value  = 'Hello World';
    this.canvas = canvas;
    this.canvas.addEventListener( 'mousemove', this.mouseMove );
}

MyObject.prototype.mouseMouse = function( evt )
{
    // this is the canvas
    var context = this.getContext( '2d' );
    context.fillText( /* how to get MyObject's value? */ , 0, 0 );
}

Thanks.

3 Answers 3

3

The callback function needs to be called in the context of the object instance. For modern browsers you can use Function.prototype.bind, which returns a function that is bound to a specific context:

this.canvas.addEventListener( 'mousemove', this.mouseMove.bind(this) );

In simpler terms, when MyObject.prototype.mouseMove gets called from addEventListener, the value of this within the function would be the canvas instance. You want the value of this to be the MyObject instance instead.

To get around this, we pass a function that is a wrapper for the function that we actually want to call. this.mouseMove.bind(this) creates a new function that wraps the mouseMove function so that the this value is the object instance instead of the canvas.

An alternative way of doing this is to create an anonymous function wrapper:

...
var self = this;
this.canvas.addEventListener( 'mousemove', function (e) {
    self.mouseMove(e);
} );

the disadvantage to this format is that you need to know how many arguments are passed to the function to pipe them through to the inner function call.

A way around this is with Function.prototype.apply:

var self = this;
this.canvas.addEventListener( 'mousemove', function () {
    //cast arguments to an array for cross-browser compatibility
    var args = Array.prototype.slice.call(arguments);
    return self.mouseMove.apply(self, args);
} );

Now if you write that kind of code a lot you'll realize that there's an easy way to abstract out the variables, all you need is a function and a context and you can generate a wrapper. That's what Function.prototype.bind does.

Sign up to request clarification or add additional context in comments.

Comments

1

You have several options to preserve MyObject context inside event listener. bind is the one and here is another:

function MyObject(canvas) {
    this.value  = 'Hello World';
    this.canvas = canvas;

    var self = this;
    this.canvas.addEventListener('mousemove', function(e) {
        self.mouseMove(e);
    });
}

Comments

0

It's quite simple and it looks like you already understand!

this.value

2 Comments

In the context of the event function, "this" is the canvas
I may have misunderstood the question, but the mouseMouse method cannot be called on the canvas property of the constructor, only the object instantiated from the constructor (because it is on the constructor's prototype).

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.