This is this in Dart

(This is part 8 in an ongoing series about Dart. Check out part 7, Strings in Dart.)

One of the things that's always confused me about JavaScript is the changing definition of this. This post will show how Dart avoids the confusion with more logical bindings.

The Problem

Here's some JavaScript code:

function Awesome() {
}

Awesome.prototype.cool = function() {
    alert("inside awesome");
}

Awesome.prototype.init = function(button) {
    button.addEventListener("click", function() {
        this.cool(); // this won't work!
    });
}

var button = document.getElementById("b");
var a = new Awesome();
a.init(button);

As you can see, I've created a simple Awesome object with two methods. The cool() method prints a simple message. The init() method adds an event listener to a button, which calls cool() when clicked.

At first glance, this seems like it will work. However, because the definition of this is relative to the current context of executing code, it does not refer to the instance of Awesome. When inside the event callback, this refers to the button!

A common pattern to address this problem in JavaScript is to declare a new variable in the function which points to this before the context is changed.

For example, the following code fixes the problem:

Awesome.prototype.init = function(button) {
    var _this = this;
    button.addEventListener("click", function() {
        _this.cool(); // this works now
    });
}

This is not intuitive to developers coming from other platforms, and requires more ceremony than is probably necessary.

Dart's Solution

The following Dart code is more clear and hopefully more logical. You can see the same structure, but the main difference is that there's no changing definition of this.

#import('dart:html');

class Awesome {

  cool() {
    window.alert("inside cool");
  }

  init(button) {
    button.on.click.add((e) => cool());
  }

}

void main() {
  new Awesome().init(document.query("#button"));
}

First, the use of this is optional. Typing less code is good.

Second, because Dart doesn't change the context, or the definition of this, the cool() method resolves to the lexical scope.

Next Steps

Read more of my Dart posts, try Dart in your browser, browse the API docs, or file an issue request. Dart is getting ready, please send us your feedback!

Read part 9, the Dart SDK Quick Tour.
5 comments

Popular posts from this blog

Converting Array to List in Scala

I ported a JavaScript app to Dart. Here's what I learned.

Minification is not enough, you need tree shaking