Tip: The way to change your "this" context in JS

I spent literally a couple evenings trying to get this to work, but if you ever need to create a callback that executes in the context of an arbitrary type, use this little guy:

inline fun <reified T> withThis(crossinline callback: T.() -> Unit): () -> Unit
        = { callback(js("this") as T) }

Then you can call it like this:

scene.preload = withThis<Scene> {
    // "this" is a Scene!
    load.image("img", "hi3")
}

Context: the main Game constructor in Phaser takes a config object with a scene key with various method callbacks that execute with a this of Scene. That is:

var game = new Phaser.Game({ // This object literal is a `GameConfig`
  scene: {
    preload: function() {
      // "this" is a `Scene`! Not a `Game`, not a `GameConfig`.
    }
  }
});

Trying to model this in Kotlin is…challenging. The only logical way to represent that preload function is as a Scene.() -> Unit, but Kotlin tries to generate weird $receiver-ish extension method-ish JavaScript that just doesn’t work. The actual this object will indeed be a Scene (when stepping through with a debugger), but any references in your code to “this” get translated into calls on $receiver, which is apparently undefined. So yeah – use the withThis helper I provided above.

Kotlin 1.2.70.

3 Likes