Sergio and the sigil

JavaScript, inner functions and private members

Posted by Sergio on 2009-02-24
This post is part of a series called JavaScript Demystified.

In our last installment in this short JavaScript series we took a look at closures. In some of the examples, we saw functions being declared (and returned) inside other functions. The capability of declaring a function inside another one is not common to all languages — C# only added this ability in version 2.0, via anonymous delegates.

Here's an example of inner functions in use.

function printPriceLong(name, price, quantity, currency) {
	var formatCurrency = function(value) {
		return value + ' ' + currency;
	};
	return 'Item: ' + name + '\n' +
		'Unit price: ' + formatCurrency(price) + '\n' +
		'Quantity: ' + quantity + '\n' +
		'TOTAL: ' + formatCurrency(price * quantity);
}

alert( printPriceLong('100g Toblerone bar', 2.09, 3, 'USD') );
/* =>
Item: 100g Toblerone bar
Unit price: 2.09 USD
Quantity: 3
TOTAL: 6.27 USD
*/

If we try to call formatCurrency from anywhere outside of printPriceLong we are going to cause an error because formatCurrency is scoped only inside its parent function.

In this example we can also see closures in action once again. The currency value is referenced inside formatCurrency but it's declared in it's parent. It's a short-lived closure, mind you, because we are not returning that inner function. It's discarded as soon as the parent function exits.

Who said JavaScript objects can't have private members?

Developers sometimes get upset when they realize that anyone has read and write access to the fields and methods of their JavaScript objects. Most of us are used to work with languages that allow us to declare some of our object's members out of reach for the calling code. We say that these members are private and we don't want anyone changing or even seeing them.

Well, this is not exactly true. If you must have private members in your JavaScript objects, you can. Inner functions and closures will come to our rescue.

Let's build on our previous example. Let's create an OrderItem object that will hold those values (name, price, etc.) Let's assume we do not want anyone changing the object's price without changing the currency at the same time (to ensure some level of consistency.) We could code our object like this:

function OrderItem(productName, price, quantity, currency) {
	//regular properties
	this.name = productName;
	this.quantity = quantity;

	//read accessors
	this.getCurrency = function(){ return currency; };	
	this.getPrice = function(){ return price; };
	//write accessor
	this.setPrice = function(newPrice, newCurrency){
		if(typeof newPrice !== 'number' || newPrice < 0){
			throw { message:'invalid price' };
		}
		if(typeof newCurrency !== 'string'){
			throw { message:'invalid currency' };
		}
		price = newPrice;
		currency = newCurrency;
	};

	//a private function
	var formatCurrency = function(value) {
		return value + ' ' + currency;
	};
	
	//methods that need private members
	this.getUnitPriceString = function(){
		return formatCurrency(price);
	};
	this.getTotalPriceString = function(){
		return formatCurrency(price * quantity);
	};
}

OrderItem.prototype = {
	//overriding the string representation of the object
	toString: function(){
		return  'Item: ' + this.name + '\n' +
			'Unit price: ' + this.getUnitPriceString() + '\n' +
			'Quantity: ' + this.quantity + '\n' +
			'TOTAL: ' + this.getTotalPriceString();	
	}
};

That seems a bit long, but hopefully we can understand what's going on here. We are letting name and quantity be regular read/write properties but we never defined properties for price or currency. We made those two values accessible via the getPrice and getCurrency methods, respectively.

The trick here is that both getPrice and getCurrency are defined inside our constructor function so they have access to the local variables price and currency. They have access to these variables even after the constructor returns (thank you closures.)

The same can be said for the setPrice method. We will use this method when we need to change the object's price. It will force us to also provide a currency.

I'll leave the explanation of the methods getUnitPriceString and getTotalPriceString as an exercise for you.

Let's instantiate one of these objects and see it in action.

var item = new OrderItem('100g Toblerone bar', 2.09, 3, 'USD');
//public methods:
alert( item.getUnitPriceString() );
// => '2.09 USD'
alert( item.getTotalPriceString() );
// => '6.27 USD'
alert(item); //this will use the toString() method
/* =>
Item: 100g Toblerone bar
Unit price: 2.09 USD
Quantity: 3
TOTAL: 6.27 USD
*/

//changing private fields
item.setPrice(1.11, 'EUR');
alert( item );
/* =>
Item: 100g Toblerone bar
Unit price: 1.11 EUR   <-- it worked!
Quantity: 3
TOTAL: 3.33 EUR
*/

//proving that price is not a field
item.price = '5.00';
alert( item.getUnitPriceString() );
// => '1.11 EUR' <-- Gotcha, smart pants!

item.setPrice(2);
//ERROR: message = 'invalid currency'
alert( item.formatCurrency(1.23) );
//ERROR: item.formatCurrency is not a function

And what am I supposed to do with this information?

I have yet to find the need to use private members in my JavaScript objects. Maybe that's because I am not shipping any JavaScript library with complex enough objects.

I think it's nice to know that you can create those off-limits values in your object. Hopefully when the need for such thing arises, we won't just say Oh, no! Can't do that!.

What about you? Have you found a use for private members in your JavaScript code? How did you get around or implemented it?

JavaScript, time to grok closures

Posted by Sergio on 2009-02-23
This post is part of a series called JavaScript Demystified.

When I wrote about functions in JavaScript I mentioned that functions are more than just a block of code:

Function is a standard data type in JavaScript, an object indeed; you can pass them around and copy them.

Let's take a look at this small sample of a function that creates and returns another function. The returned function accepts one string argument and returns another string repeating the argument a number of times.

function makeRepeater(times){
	return function(text){
		var message = '';
		for (var i=0; i < times; i++) {
			message += text + ' ';
		}
		return message;
	};
}

Let's now write some code that uses that function.

var threeTimes = makeRepeater(3);
var fourTimes = makeRepeater(4);
alert( threeTimes('hi') );
// => 'hi hi hi '
alert( fourTimes('hi') );
// => 'hi hi hi hi '

Nothing spectacular, right? But look closely. The function returned by makeRepeater contains a reference to times, which is a local variable of makeRepeater. When we call threeTimes or fourTimes the makeRepeater call has already returned and times should be out of scope. Or should it?

Extra life for your local scope

You may try to argue and say that the times inside threeTimes is not a reference to the times from makeRepeater, but just a copy of that value. Well, sadly I'll have to prove you wrong. Let's modify our code just a little.

var times;
function makeRepeater(){
	return function(text){
		var message = '';
		for (var i=0; i < times; i++) {
			message += text + ' ';
		}
		return message;
	};
}

times = 3;
var threeTimes = makeRepeater();
times = 4;
var fourTimes = makeRepeater();
alert( threeTimes('hi') );
// => 'hi hi hi hi '  ---> What?!?!
alert( fourTimes('hi') );
// => 'hi hi hi hi '

If it's not clear yet, let me write it down for you. The returned function really keeps a reference to any outside values it will need when invoked. In our original example, it kept a reference to the times local variable at the time it was produced. If we had created other local variables inside makeRepeater they would also become available inside the returned function. In other words, all the scope created during the call to makeRepeater will be preserved for the returned function. This happens when the returned (or inner) function has a reference to anything defined in the parent (or outer) function, i.e. the parent local scope. When this happens, we say that a closure has been created.

Closures can be tricky

It's important to understand the mechanics of closures to avoid subtle bugs in our code. Look at this piece of code, adapted from a real bug I had to fix.

<input type="button" value="Button 1" id="btn1">
<input type="button" value="Button 2" id="btn2">
<input type="button" value="Button 3" id="btn3">

<script type="text/javascript">
	function createEventHandlers(){
		var btn;
		for(var i=1; i <= 3; i++){
			btn = document.getElementById('btn' + i);
			btn.onclick = function(){
				alert('Clicked button #' + i);
			}
		}
	}
	createEventHandlers();
</script>

If you put this code in a page and click the three buttons you will see that all of them will show the message "Clicked button #4". Armed with our understanding of closures we can immediately understand that this bug is being caused by that reference to i used inside the event handler. We can fix that.

function createEventHandlers(){
	var btn;
	for(var i=1; i <= 3; i++){
		btn = document.getElementById('btn' + i);
		btn.onclick = createOneHandler(i);
	}
}

function createOneHandler(number){
	return function() {
		alert('Clicked button #' + number);
	}
}

The above code works because we are not creating functions inside the for loop, hence not producing closures on the same local scope. There is a different set of closures being produced by createOneHandler, but those are not pointing to the same parent scope. Each of these three new closures contain a different scope, created by each call to createOneHandler

Closing thoughts

Closures, of course, are not an exclusive feature of JavaScript. It's a very important trait of functional languages. Even in C#, when we use lambdas, closures are created — many times without us noticing.

The key to properly using closures in our code is to pay attention to locally scoped values from the outer function being used in the body of the inner function. Most of the times this will work as intended by the developer but, when it doesn't, stop and check if more than one closure is sharing the same local scope or if these local values are changing between the inner function creation and its invocation.

JavaScript, 5 ways to call a function

Posted by Sergio on 2009-02-09
This post is part of a series called JavaScript Demystified.

Time after time I find JavaScript code that has bugs caused by lack of proper understanding of how functions work in JavaScript (a lot of that code has been written by me, by the way.) JavaScript has functional programming characteristics, and that can get in our way until we decide to face and learn it.

For starters, let's examine five ways to invoke a function. On the surface we might be tempted to think that functions work exactly like C#, but we will see that there are important differences and ignoring them will undoubtedly result in hard to track bugs.

Let's first create a simple function that we will be using through the rest of this post. This function will just return an array with the current value of this and the two supplied arguments.

<script type="text/javascript">
function makeArray(arg1, arg2){
	return [ this, arg1, arg2 ];
}
</script>

Most common way, unfortunately, global function calls

When we are learning JavaScript we learn how to define functions using the syntax used in the example above. We learn that it's also very easy to call that function — all we need to do is:

makeArray('one', 'two');
// => [ window, 'one', 'two' ]

Wait a minute. What's that window object doing there? Why is it the value of this? If you haven't stopped to think about it, please stay with me here.

In JavaScript, and I'm not talking specifically about the browser here, there's a default/global object. It's as if every code that we write which seems to be just "loose" inside your script (i.e. outside of any object declaration) is actually being written in the context of that global object. In our case, that makeArray function isn't just a loose "global" function, it's a method of the global object. Bringing ourselves back to the browser, the global object is mapped to the window object in this environment. Let's prove that.

alert( typeof window.methodThatDoesntExist );
// => undefined
alert( typeof window.makeArray);
// => function

What all this means is that calling makeArray like we did before is the same as calling as follows.

window.makeArray('one', 'two');
// => [ window, 'one', 'two' ]

I say it's unfortunate that this is the most common way because it leads us to declare our functions globally by default. And we all know that global members are not exactly the best practice in software programming. This is especially true in JavaScript. Avoid globals in JavaScript, you won't regret it.

JavaScript function invocation rule #1 In a function called directly without an explicit owner object, like myFunction(), causes the value of this to be the default object (window in the browser).

Method call

Let's now create a small object and use the makeArray function as one of its methods. We will declare the object using the literal notation. Let's also call this method.

//creating the object
var arrayMaker = {
	someProperty: 'some value here',
	make: makeArray
};

//invoke the make() method
arrayMaker.make('one', 'two');
// => [ arrayMaker, 'one', 'two' ]
// alternative syntax, using square brackets
arrayMaker['make']('one', 'two');
// => [ arrayMaker, 'one', 'two' ]

See the difference here? The value of this became the object itself. You may be wondering why isn't it still window since that's how the original function had been defined. Well, that's just the way functions are passed around in JavaScript. Function is a standard data type in JavaScript, an object indeed; you can pass them around and copy them. It's as if the entire function with argument list and body was copied and assigned to make in arrayMaker. It's just like defining arrayMaker like this:

var arrayMaker = {
	someProperty: 'some value here',
	make: function (arg1, arg2) {
		return [ this, arg1, arg2 ];
	}
};
JavaScript function invocation rule #2 In a function called using the method invocation syntax, like obj.myFunction() or obj['myFunction'](), causes the value of this to be obj.

This is a major source of bugs in event handling code. Look at these examples.

<input type="button" value="Button 1" id="btn1"  />
<input type="button" value="Button 2" id="btn2"  />
<input type="button" value="Button 3" id="btn3"  onclick="buttonClicked();"/>

<script type="text/javascript">
function buttonClicked(){
	var text = (this === window) ? 'window' : this.id;
	alert( text );
}
var button1 = document.getElementById('btn1');
var button2 = document.getElementById('btn2');

button1.onclick = buttonClicked;
button2.onclick = function(){   buttonClicked();   };
</script>

Clicking the first button will display "btn1" because it's a method invocation and this will be assigned the owner object (the button input element.) Clicking the second button will display "window" because buttonClicked is being called directly (i.e. not like obj.buttonClicked().) This is the same thing that happens when we assign the event handler directly in the element's tag, as we have done for the third button. Clicking the third button does the same of the second button.

That's another advantage of using a library like jQuery. When defining event handlers in jQuery, the library will take care of overriding the value of this and make sure it contains a reference to the element that was the source of the event.

//using jQuery
$('#btn1').click( function() {
	alert( this.id ); // jQuery ensures 'this' will be the button
});

How does jQuery override the value of this? Keep reading.

Two more: apply() and call()

The more you leverage functions in JavaScript, the more you find yourself passing functions around and needing to invoke them in different contexts. Just like jQuery does in the event handler functions, you'll often need to override the value of this. Remember I told you functions are objects in JavaScript? Functions have predefined methods, two of them are apply() and call(). We can use them to do precisely that kind of overriding.

var gasGuzzler = { year: 2008, model: 'Dodge Bailout' };
makeArray.apply( gasGuzzler, [ 'one', 'two' ] );
// => [ gasGuzzler, 'one' , 'two' ]
makeArray.call( gasGuzzler,  'one', 'two' );
// => [ gasGuzzler, 'one' , 'two' ]

The two methods are similar. The first parameter will override this. They differ on the subsequent arguments. Function.apply() takes an array of values that will be passed as arguments to the function and Function.call() takes the same arguments separately. In practice I believe you'll find that apply() is more convenient in most cases.

JavaScript function invocation rule #3 If we want to override the value of this without copying the function to another object, we can use myFunction.apply( obj ) or myFunction.call( obj ).

Constructors

I won't delve into the details of defining types in JavaScript but at minimum we should be aware that there aren't classes in JavaScript and that any custom type needs a constructor function. It's also a good idea to define the methods of your type using the prototype object, which is a property of the constructor function. Let's create a small type.

//declaring the constructor
function ArrayMaker(arg1, arg2) {
	this.someProperty = 'whatever';
	this.theArray = [ this, arg1, arg2 ];
}
// declaring instance methods
ArrayMaker.prototype = {
	someMethod: function () {
		alert( 'someMethod called');
	},
	getArray: function () {
		return this.theArray;
	}
};

var am = new ArrayMaker( 'one', 'two' );
var other = new ArrayMaker( 'first', 'second' );

am.getArray();
// => [ am, 'one' , 'two' ]

What's very important to note here is the presence of the new operator before the function call. Without that your function will just be called like a global function and those properties that we are creating would be created on the global object (window.) And you don't want to do that. Another issue is that, because you typically don't have an explicit return value in your constructor function, you'll end up assigning undefined to some variable if you forget to use new. For these reasons it's a good convention to name your constructor functions starting with an upper case character. This should serve as a reminder to put the new operator before the call.

With that taken care of, the code inside the constructor is very similar to any constructor you probably have written in other languages. The value of this will be the new object that you are trying to initialize.

JavaScript function invocation rule #4 When used as a constructor, like new MyFunction(), the value of this will be a brand new object provided by the JavaScript runtime. If we don't explictly return anything from that function, this will be considered its return value.

It's a wrap

I hope understanding the differences between the invocation styles help you keeping bugs out of your JavaScript code. Some of these bugs can be very tricky do identify and making sure you always know what the value of this will be is a good start to avoiding them in the first place.