Saturday, August 2, 2014

Execution Context Best Practices in JavaScript


In this article we'll see what this means, and places where this is applicable. 
We'll also look at how to manipulate this with built-in functions like 
apply, call and bind.

Every JavaScript statement is executed in one execution context or the other. In it's simplest terms this refers to the "owner"  of  the function we currently executing. this helps us to get the object or the execution context we are currently working with.

In the above example both func1 and func2 returns this. because f1 was called (executed) inside the window (or global context) func1 returns window. In f2 we are using strict mode. In strict mode, this will be whatever it's set to when entering the execution context. Since we have not defined this, it will remain undefined. We can set that to any value we want. Even null. 


In the above example we are creating 3 variables with the same name 'val'. One in the global context, one inside obj and the other inside the innerMethod of obj. JavaScript resolves identifiers within a particular context by going up the scope chain from local to global.

Below we'll look at 4 scenarios this applies

Calling a method of a object


When line1 is executed, JavaScript establishes an execution context (EC) for the function call, setting this to the object referenced by whatever came before the last ".". so in the last line you can understand that a() was executed in the global context which is the window.


Constructor

When defining a function to be used as a constructor with the new keyword, this can be used to refer to the object being created. 

when new Person() is executed, a completely new object is created. Person is called and its this is set to reference that new object. The function can set properties and methods on this. which returned at the end of Person's execution. We entered Person via new so this meant "the new object".


Function call


If we don't provide a context by new (as explained above), whatIsThis defaults to reference the most global context it can find (window) and it will pollute the global object too. But whatIsThis2 acts as we expect since we are providing new there. Therefore make sure to put new keyword otherwise you'll be adding unnecessary variables to global context.


Event Handler

If the event handler is inline, this refers to global window object. 

When we add event handler via. JavaScript, this refers to the DOM element that generated the event. 

Let's look at more complicated example

Here when you click thebutton it alerts undefined.


Problem: We've passed a reference to the sayHello method, which when executed as an event handler, runs in a different context than when it's executed as an object method. Here this refers to the DOM element. setTimeout exhibits the same behavior, delaying the execution of a function while at the same time moving it out into a global context. 

Manipulating context with .apply and .call


The call method (also the apply method) allows us to specify the this object in which the function needs to get executed. 


Even though we apply .call there's a problem. call executes this immediately. Instead of providing a function reference to click handler, we are giving the result of an executed function. 

Let's get introduced to .bind(). bind performs the same general task as call. altering the context in which a function executes. The difference is bind returns a function reference which can be used later rather than the result from immediate execution which call does. Let's see a basic example.




Now we'll create bind method on the Function object's prototype, which makes bind available for all functions in our program. (More info)


When multiply.bind(obj) is called, JavaScript creates an execution context for bind method, setting this to multiply function, and setting the 1st argument obj to refer first_object.

example 2


The beauty of this solution is creation of method and setting it to this. 
When the anonymous function is created on next line, method is accessible via its scope chain, as is obj (this couldn't be used here, because when newly created func. is executed, this will be overwritten by a new, local context) This alias to this makes it possible to use apply to execute the mulitply function, passing in obj to ensure that the context is set correctly. temp is a closure that when returned at the end of bind call, can be used in any context what so ever. 

Other : Chaining .bind()

JQuery Proxy
JQuery Proxy is another way you can use to make sure this in a function will be the value you desire. It takes a function as the input and returns a new one that will always have a particular context. Read following articles Understanding jQuery proxy and usage of jQuery proxy for more information.

0 comments:

Post a Comment

Powered by Blogger.


Software Architect at Surge Global/ Certified Scrum Master

Experienced in Product Design, Software Engineering, Team management and Practicing Agile methodologies.

Search This Blog

Facebook