Skip to content

Instantly share code, notes, and snippets.

@datacarl
Created September 24, 2013 17:23
Show Gist options
  • Save datacarl/6688180 to your computer and use it in GitHub Desktop.
Save datacarl/6688180 to your computer and use it in GitHub Desktop.
Problems accessing this when using prototypal pattern for prototypal inheritance.
var transition = {
create: function() {
// Assign to self, but this will only be accessible inside the create function.
var self = Object.create(this);
self.circle = new Kinetic.Circle({
x: 10,
y: 10,
});
self.start();
return self;
},
start: function() {
// self will be undefined here. All I can do is:
var self = this;
// and then pass self.next to the callback of the circles transitionTo function. So far that's ok, the
// correct callback is called.
this.circle.transitionTo({
x: 12,
y: 12,
callback: self.next,
});
},
next: function() {
// In the callback however, self is (still) not defined and I cannot access it through this, since this is now
// an instance of a Kinnetic circle.
// So I cannot access this.circle, and when I want to pass the next method as the callback again, I cannot
// access it either.
this.circle.transitionTo({
x: 14,
y: 14,
callback: self.next,
});
},
};
@aaditmshah
Copy link

In my humble opinion you should refactor your start function as follows:

function () {
    var self = this;

    this.circle.transitionTo({
        x: 12,
        y: 12,
        callback: next
    });

    function next() {
        self.circle.transitionTo({
            x: 14,
            y: 14
            callback: next
        });
    }
}

The problem here is not the prototypal pattern of prototypal inheritance. The problem is that KinectJS calls back functions binding its own instances to the callback's this pointer. Another way to tackle this problem would be to use bind as follows:

start: function () {
    this.circle.transitionTo({
        x: 12,
        y: 12,
        callback: this.next.bind(this)
    });
},
next: function () {
    this.circle.transitionTo({
        x: 14,
        y: 14,
        callback: this.next.bind(this)
    });
}

Ideally however the first method is more optimal. It's more readable and since it's a closure you don't need to keep binding this to this.next every time. You would do the same using the constructor pattern of prototypal inheritance as well:

function Transition () {
    this.circle = new Kinetic.Circle({
        x: 10,
        y: 10
    });

    this.start();
}

Transition.prototype.start = function () {
    var self = this;

    this.circle.transitionTo({
        x: 12,
        y: 12,
        callback: next
    });

    function next() {
        self.circle.transitionTo({
            x: 14,
            y: 14
            callback: next
        });
    }
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment