Mustache and Handlebars deal with scoping differently and this doesn’t seem to be explicitly picked up in any comparisons I’ve found of the two libraries.

Mustache and Handlebars

Both Mustache and Handlebars are well-documented templating libraries and you can find more on the specifics of their usage here and here respectively. I have been trying out the JavaScript version of Mustache for direct comparison with Handlebars, which is natively JavaScript. You can also try both libraries out without any installation at http://trymustache.com and http://tryhandlebarsjs.com respectively.

A quick summary of how both work would be to say that you create an HTML template with variables in it placed in double curly braces like this:

{{variable}}

In context it might look like this:

<span>{{variable}}</span>

For each of these variables, you create a property within a context object (in JSON format) which looks like this.

{
	"variable": "Some value."
}

When the template is interpreted or compiled, the variables are subjected with the corresponding variable from the context object. If a particular variable is missing, it usually returns blank.

Here’s how the result of combining the HTML above with the context-object above would come out:

<span>Some text.</span>

Pretty simple stuff.

Hash, or pound, signs

When writing a template with either Mustache or Handlebars, you can prefix a variable name with a # in order to create a wrapper. One closes the wrapper with the same variable prefixed with /, a bit like closing an HTML tag. For example:

{{#wrapper}}<b>Hello World!</b>{{/wrapper}}

How this is interpreted by either library depends on the variable’s type and value in the context object. I’ve listed each type below, with example context code and results.

Type Truthiness Example Value HTML Output
Boolean Truthy true <b>Hello World!</b>
Boolean Falsy false  
String Truthy "Wrapper" <b>Hello World!</b>
String Falsy ""  
Number Truthy 5 <b>Hello World!</b>
Number Falsy 0  
Object Truthy {} <b>Hello World!</b>
Object Truthy { "property": "value" } <b>Hello World!</b>
Object Truthy { "property": "value", "property2": "value2" } <b>Hello World!</b>
Array Truthy [ "hello world" ] <b>Hello World!</b>
Array Truthy [ "hello", "world" ] <b>Hello World!</b><b>Hello World!</b>
Array Truthy [ { "property": "value" } ] <b>Hello World!</b>
Array Truthy [ { "property": "value" }, { "property": "value" } ] <b>Hello World!</b><b>Hello World!</b>
Array Truthy []  

For most types, if the value is truthy, then everything in the wrapper is printed. In this way the {{#wrapper}} acts as a conditional.

For arrays, behaviour is slightly different. Whereas an empty object is still truthy and will therefore print whatever is in the wrapper, an empty array is treated as if it were falsy, and will print nothing. Furthermore, if there are two elements inside the array, it will print the content within the wrapper twice. In short, with an array, the content is printed as many times as there are elements in the array, even if those elements themselves happen to be falsy.

The use of an array means the wrapper is treated like a block, rather than a straightforward conditional.

Nested variables

Where the two libraries differ is in the handling of variables inside a wrapper.

Take the following line which might appear in a template:

{{#wrapper}}<b>Hello {{name}}!</b>{{/wrapper}}

In either library, if name is not defined at all, then the HTML return would reflect that.

Here’s an object structure where that’s the case:

{
	"wrapper": true
}

And here’s the result with either library:

<b>Hello !</b>

There is no name property in the context variable, ergo it does not display.

However, the differences arise in where the variable can be defined for each library.

Your object structure might look like this:

{
	"wrapper": true,
	"name": "Guy"
}

We already know that wrapper has to be true, in order for any HTML to be printed. However, the placement of name as a property within the same parent object as wrapper has different results depending on which library you use.

In Mustache, you get this:

<b>Hello Guy!</b>

In Handlebars, you get this:

<b>Hello !</b>

Handlebars acts as if the name property did not exist at all. We could say that, for Handlebars, name is out of scope.

Handlebars’ scope limitations

In Handlebars, once you are inside a wrapper, only variables defined within that block can be accessed. So the following object in Handlebars …

{
	"wrapper": { "name": "Guy" }
}

… would give us:

<b>Hello Guy!</b>

This object, where wrapper is an array containing an object with the name property…

{
	"wrapper": [
		{ "name": "Guy" }
	]
}

… produces the same result:

And of course if the array consists

This would also work in Mustache. But whereas Handlebars will not automatically look for name outside the wrapper context (more on that “automatically” remark later), Mustache will.

Mustache’s scope availability

What Mustache also does is checks outside the wrapping context for the variable.

We have already seen that, in Mustache, this template…

{{#wrapper}}<b>Hello {{name}}!</b>{{/wrapper}}

… with this object …

{
	"wrapper": true,
	"name": "Guy"
}

… produces this:

<b>Hello Guy!</b>

If we also define, a name property inside the wrapper, like this …

{
	"wrapper": { "name": "Rosie" },
	"name": "Guy"
}

… then the inner variable (the one most local) takes precedence over the outer.

Therefore the result in this case will be:

<b>Hello Rosie!</b>

The outer name property will be ignored, but can act as a fallback, should the inner variable prove to be nonexistent.

This is somewhat reminiscent of JavaScript behaviour around variables and scoping. If a local variable cannot be found, JavaScript will check the outer scope to see if one exists there and then the scope around that, all the way back to the global scope.

Yet the only mention I could find of this difference in any of the documentation or any of the comparative posts I’ve read around it is one line a section of the Handlebars GitHub README file on compatability, namely:

Handlebars deviates from Mustache slightly in that it does not perform recursive lookup by default.

There is a flag for enabling recursive lookup (i.e., bubbling out of local scope for variable fallback) but, by default Handlebars has different methods for accessing variables beyond scope.

Referencing the wrapper from within

This has consequences for the way the conditional pound sign can be used in each library.

Take the following context object:

{
	"value": "Some text."
}

Then take the following templating code:

{{#value}}<span class="text">{{value}}</span>{{/value}}

We know that value is truthy and not an empty array. Therefore we know that the <span> tags will be printed, whichever library we use. However, how the value in the middle is printed depends on the library.

In Mustache, we will get:

<span class="text">Some text.</span>

This is because Mustache reaches out to find value outside of the context of value.

In Handlebars, however we get:

<span class="text"></span>

The HTML tags are printed because value is truthy and not an empty array. But once inside the value wrapper, Handlebars does not automatically go back out of it to get value. It can see no value in the value context and so does not print.

If you wanted to the wrapper to self-reference in Handlebars you could use a reserved variable called this to print value which conditionally checking it exists.

{{#value}}<span class="text">{{this}}</span>{{/value}}

Another way to access the value variable from within the wrapper is by using paths.

Handlebars paths

Handlebars can access variables outside a wrapper scope or context but only if you manually specify that it should.

One way to do this with the “self-referencing” example above is to write

{{#value}}<span class="text">{{../value}}</span>{{/value}}

The ../ tells Handlebars to go up one context. It takes us outside the wrapper for the one variable and back into the parent object. One can use several of these to go up as many contexts.

In this way it’s possible to first check that value exists, then write the HTML code for it, include the value itself, and then the rest of the HTML code before closing the wrapper.

Paths aren’t just a way of getting around the Mustache automatic fallback technique. They give you a lot for control over where you get the variables from.

Which is better?

In my opinion, Handlebars’ paths and self-referencing variables are more powerful. Besides Handlebars’ other advantages over Mustache, these features allow for more control and should make for easier debugging. I’ll keep playing around with both, particularly as Scriptogram (my current blogging platform) seems to use Mustache, but right now for me Handlebars wins out.