Syntatic sugar makes for more human-readable code and, if done

correctly, provides for more flexibility. In the world of Node

many turn to Coffeescript to add that “sweetness”,

but you can also achieve it with plain old Javascript. TL;DR »

Object.defineProperty

It all comes down to using defineProperty of the

Object class. Introduced as part of ECMAScript 5 and

implemented in Javascript 1.8.5 – which is supported by Node and most

major browsers – it allows you to add or modify

a property on an object by not just determining its value but its

entire behaviour.

Object.defineProperty(obj, prop, descriptor)

The magic comes in the descriptor parameter. You can

directly set an initial value that will always be returned

by anyone using the property. You can use other attributes in the

descriptor to make the property

writable (allowing new values assigned),

configurable (permit further changes), and

enumerable (returned during property enumeration).

But you can go beyond the simple retrieval and assignment of value to

properties by passing functions as the get and/or set

attributes in the descriptor.

Let’s see how we can use it to add our sugar.

An Example: Read-only Attributes

Recently I published nock-vcr, a node module to deliver

the same functionaly of the Ruby gem VCR but built atop the HTTP

mocking framework nock. VCR use the metaphor of “cassettes”

to record the HTTP interactions, with the interactions being written

out to a file named after the name given to the cassette. If a

cassette doesn’t exist at the time of recording, it will be created.

For various reasons, we don’t want to give users of the module

the ability to change the name of a Cassette

once an instance is created. This is accomplished by using

Object.defineProperty to explicity set the

value :

Now when we instantiate an instance of Cassette , the string

passed in the construtor is returned by the name property.

More importantly, because we never set the writable

attribute in the descriptor to true , no one can assign

a new value to the property:

Now Add the Syntactic Sugar

At this point, we haven’t done anything to “sweeten” the syntax. An

opportunity arises in implementing exists . If implemented

as a function, it would be used as follows:

if(cassette.exists())

But wouldn’t it be sweeter to do the following?

if(cassette.exists)

In this case, we pass in a get function when defining

‘exists’ as a property. This function will be run every time the property is

referenced, ensuring it represents the current state of the cassette, but without

need of keeping tract with another attribute.

Now we can call exists without need of the parenthesis:

A small, “sweet” victory.

Another Example: Sweeter Tests

The previous example did not really gain us much; what are a couple of

parenthesis in the larger scheme of things? A more useful example of this

technique and the benefits of syntactic sugar comes in writing out a

chai-like test framework called rooibos .

Let’s begin by creating an Assertion “class”, that accepts a

value we will be running our assertions against. We will also create and

export expect function as the only interface into our framework and

creating these assertions.

We can add two basic assertions; truthy which will

assert if the value is non-falsy and empty , which asserts

the value is has no characters if a string, no elements if an array, and

is non-null or undefined in all other cases.

At this point, we can use the framework as follows:

We can sweeten this further with to and be properties that pass through the Assertion instance, doing nothing but enhancing readability.

So finally we can write our tests with the sweetest syntax of all: