[Coding] JavaScript and the ‘this’ Keyword

Posted by Khatharsis on June 15, 2014

I ran across an interesting article on the O’Reilly programming website on using JavaScript without the ‘this’ keyword. While it sounds plausable to implement, and may even be the direction developers head towards (eventually), I found it conflicts with my preferred dynamic namespacing pattern using this as a proxy. I’ll refer to the pattern as “dynamic namespacing” for short in this post, but just be aware there are other tweaks that fall under this shortened general label.

A quick recap of my preferred pattern via example:

var APP = {};
(function() {
	var that = this;
	
	this.describe = function() {
		return 'Hi, I am blue.';
	};
	
}).call(APP);

APP.describe();	// returns 'Hi, I am blue.'

Following Crockford’s suggestion of keeping global variables to a minimum, I set up the global APP variable, then use dynamic namespacing to add a describe() method to it. I invoke describe() as an example afterward. Out of habit, I set up a local that variable.

The purpose of using a that, which also represents this, is when I make visible two functions and one function needs to invoke another. See the below example of a second public method added:

var APP = {};
(function() {
	var that = this;
	
	this.ornament = function() {
		return 'Daa boo dee.';
	};
	
	this.describe = function() {
		return 'Hi, I am blue. ' + that.ornament();
	};
	
}).call(APP);

APP.describe();	// returns 'Hi, I am blue. Daa boo dee.'


The use of this/that is necessary in the way I have set up my pattern. If I tried to define describe() as return 'Hi, I am blue.' + ornament();, i.e., without this/that, I will get an error (“ornament is not defined”).

I can use this instead of that in the working definition above, but the main purpose of setting up a that variable is to preserve what this is referring to. Things can get a little murky when calling multiple functions and getting nested, resulting in the intended, expected value of this getting lost along the way. So, I now include a that variable at the top of each dynamic namespace. (See also this post linked earlier for more.)

The “pattern” used in the O’Reilly article is less of avoiding polluting the global namespace and more about getting across a concept. As a result, attempting to substitute the “guts” of my dynamic namespace with their example resulted in errors:

var APP = {};
(function() {
	var that = this;
	
	function describe() {
		return 'Hi, I am blue.' + that.ornament();
	}
	
	return {
		describe: describe;
	};
}).call(APP);

APP.describe();	// error: "APP.describe is not a function"

Returning an object doesn’t work with my dynamic namespacing pattern. The point of returning an object within a function is to choose what to make public and what not to make public. In my pattern, I already choose what to expose and what not to expose by using this as a proxy. Consider:

var APP = {};
(function() {
	var that = this;
	
	function ornament() {
		return 'Daa boo dee.';
	}
	
	this.describe = function() {
		return 'Hi, I am blue. ' + ornament();
	};
	
}).call(APP);

APP.describe();	// returns 'Hi, I am blue. Daa boo dee.'
APP.ornament(); // error: "APP.ornament is not a function"

I made ornament() “private” by using the named declaration syntax for a function declaration. Normally a named declaration syntax (as used in the O’Reilly article) becomes tied to the global namespace, but since I am using dynamic namespacing, there is no pollution. Attempting to call ornament by itself will result in a “not defined” error.

I can also make a function private by expressing it as a variable (e.g., var ornament = function() { ... };), but instead of throwing an error when attempting to call it, it will return undefined instead. See this StackOverflow page for more on function declaration vs. function expression.

By using this on functions, I am declaring the method as a property of the object APP and also its public visibility.

I’m not entirely sold on trying to remove this from use as I find it to be a little more elegant than the haphazard examples in the article. Again, the examples are mainly to get a concept across and not actually within a popular pattern. There is a dynamic namespacing pattern that doesn’t use this, but instead passes the namespace object as an argument to the dynamic namespace. However, that is just a variation that can be reduced to using this but using aliases instead (similar to that).

If I saw a better example, I might change my mind. From the comments, it seems like Crockford is also moving away from using this, but I have to see his talk on “The Better Parts” to try to understand his point of view. Given how often his name and book is thrown around, I am concerned that the use of this may become frowned upon as technology practices continue to evolve (sometimes not always for the better).