In various pieces of sample code, within the SDK samples as well as those in my book, you’ll often see the following syntax that appears somewhat cryptic (as does much of JavaScript!) to the uninitiated:

this.<some_function>.bind(this));

For example, when wiring up app bar buttons in the book’s Here My Am! examples, you’ll see this code:

var appbar = document.getElementById(“appbar”).winControl;
appbar.getCommandById(“cmdRefreshLocation”).addEventListener(“click”, this.tryRefresh.bind(this));
appbar.getCommandById(“cmdPickFile”).addEventListener(“click”, this.pickFile.bind(this));
appbar.getCommandById(“cmdRecentPictures”).addEventListener(“click”, this.recentPictures.bind(this));

The use of .bind also appears in other contexts, again from Here My Am!:

var image = document.getElementById(“photo”);
image.addEventListener(“click”, capturePhoto.bind(image));

So what’s happening here? Let’s take a step back and talk about the this keyword more generally.

this is an intrinsic variable that typically refers to the current object context on which a method is called. For example, if I have an object named obj1 and I call its obj1.doSomething method, then this inside doSomething will refer to obj1.

If I just have a global function, on the other hand, this in that context will typically be the same as window (the global context).

Event handlers present a particular difficultly with getting the this context set correctly. If you’ve defined an event handler as a member of some object, say obj1.eventHandler, and pass that function to something like addEventListener or assign it to someOtherObject.onEvent, the element/object raising that event doesn’t have your obj1 object through which to call the handler. That is, when JavaScript resolves an identifier like obj1.eventHandler, the result is just a standalone function object which has no context of where it came from.

As a result, if you do something like document.getElementById(“myButton”, obj1.eventHandler) then the function will be called, all right, but the this object within that handler will contain the global context (window) and not obj1.

The bind method solves this problem. By calling it you say, “here’s the object context through which I want this method called,” which is to say, “make this refer to a particular object when you call the method.” So if you document.getElementById(“myButton”, obj1.eventHandler.bind(obj1)) then the this object within eventHandler will, in fact, be set to obj1.

When you see the this.<event>.bind(this) syntax then, you’re just seeing an object wire one of its own methods up as an event handler and making sure that this will remain the same in the event handler.

So in the Here My Am! examples above, the event handler for the app bar buttons exist as part of the page control where this code appears. The this variable thus points to that page control object, so when the events are triggered, the handlers like tryRefresh, defined in that same page control, will have their this values set to the page control as we want.

In the second example, capturePhoto.bind(image), what we’re doing instead is making sure that the specific image element that was tapped shows up as the this object within the capturePhoto function. There are other ways to do this (getting the originating element for the event, for example), but using .bind here works nicely.


3 Comments

  1. Kashyap Mukkamala
    Posted January 31, 2013 at 2:51 am | Permalink

    var image = document.getElementById(“photo”);
    image.addEventListener(“click”, capturePhoto.bind(image));

    on page number 76 is not clear; it does not say where it should be placed (unlike the other section of the code).

    My map is showing up fine but I am unable to get the photo from the webcam.

    Also, the statement

    if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated)

    in the default.js stream was troubling me as I could not understand what to write in this section
    (the default code that is generated here says something like this –> // TODO: This application has been newly launched. Initialize your application here.) so I just left it blank!! and it still works. Can you please explain why this is happening??

    • Kashyap Mukkamala
      Posted January 31, 2013 at 8:02 am | Permalink

      Hey!! I finally worked it out! Amazing blog u have sir!!

      • Posted January 31, 2013 at 7:46 pm | Permalink

        Glad you sorted it out. When I revise the book I’ll make it clear that this particular piece of code can go anywhere in the activated event. Because the activated event is fired after DOMContentLoaded, you can be assured that the elements in the HTML have been instantiated by then, so getElementId will work. It’s the WinJS controls you have to watch for, as you can only talk to them after the async WinJS.UI.processAll has completed (so you put further initialization of those controls inside the completed function you pass to .done).

        If you’re having trouble with the webcam, perhaps you didn’t set the Webcam capability in the manifest? If you forget that, the capture APIs will fail.

        As for the check on previousExecutionState, I talk about that in Chapter 3. The case where it’s not “terminated” is for normal activation as opposed to the app restarting after the system terminated it due to low memory. Those two cases are just to differentiate how you might be reloading previously saved state from appdata, e.g. whether you’re rehydrating the app (including the nav stack and form data), or whether you’re initializing from defaults. Again, that’s in Chapter 3, pages 109-116, in the section “App Lifecycle Transition Events and Session State.” You’ll see those two cases in the activated handler on Page 114.

        The short of it is that any initialization code that isn’t related to the previous app state can go outside of that whole if-else statement. It’s only those things that are different between normal launch and the terminate-restart case that are affected.