The Anatomy of a JavaScript Function

Functions in JavaScript are like classes to Java. They’re the fundamental modular unit: the cell in life, the note in music, the word in language, the funky chicken in dance. JavaScript functions are full fledged objects, often called first-class objects[1], having properties and methods, mutable values, and dynamic memory. Douglas Crockford, one of the early gurus and longtime critic of the language wrote[2]:

The best thing about JavaScript is its implementation of functions.

In this post I cover the qualities of functions as objects, how function objects are created, the difference between constructor, prototype, and instance objects, how the new operator works, and useful properties of functions.


First Class Objects #

Functions have the same capabilities as other objects. So it’s no secret they can be:

passed as arguments

function a() { ... }
function b(a) { ... }
b(a);

returned from functions

function a() {
    function b() { ... }
    return b;
}

assigned as data values

var a = function() { ... };

have properties and methods

function a() { ... }
var obj = {};
a.call(obj);

defined anywhere an expression can be, allowing them to be nested

function a() {
    function b() { 
        function c() {
            ...
        }
        c();
    }
    b();
}
a();


Constructors, Prototypes, & Instances #

Before we look at function internals let’s quickly review the basics of prototypes. Every function carries a prototype property linked to an internal prototype object[3]. When a function is invoked as a constructor to create instance objects, which we’ll cover shortly, those instance objects carry the link to the same prototype object, giving them shared behavior across instances.

The key to understanding functions is in the relationship between three objects:

Let’s focus on the first two. The built-in Function constructor object is itself a function, having a prototype property that references it’s prototype object thru Function.prototype[3]. These two objects are built into the JavaScript runtime before any of our code starts executing.

We can visualize them in memory.
funcobjtop.png

Creating Function Instances #

Meet 2 functions.

function Alpha() { ... }
function Bravo() { ... }

The simple function keyword is a workhorse. When these two functions are defined:

[3]

Augmenting Prototypes #

We can also define methods on their prototype objects by referencing the constructor function’s prototype property,

Alpha.prototype.doStuff = function() { ... };

Our Alpha instance and any object instances created by it have access the prototype’s shared methods.

After defining these two functions and augmenting Alpha.prototype, we have:
funcobjmid.png
[3]

Note, internal properties are displayed inside double brackets.

The result is two function instance objects, referenced thru Alpha and Bravo. They link to the single Function.prototype thru their [[prototype]] property, giving them access to the prototype’s useful methods, such as .call() and .apply().


new Operator #

Let’s take this a step further. We invoke function instance object Alpha with the new operator, treating it as a constructor function.

var alpha1 = new Alpha();
var alpha2 = new Alpha();

Similar steps as above occur, with some variation,

[3]

In short, we used new to invoke Alpha as a constructor function, creating two instance objects referenced as alpha1 and alpha2. The key differences here from when function object Alpha was created is alpha1 and alpha2 are objects but are not functions, so they don’t have prototype objects.

And our objects in memory now look like:

funcobjbot.png


Function Instance Properties #

We briefly covered how function instance objects contains several internal properties and methods designed for its execution. It’s worthwhile to have a general understanding of these:

Property Value Description
prototype Automatically created for every function, providing the possibility that the function will be used as a constructor[3]
[[Code]] Function body code between { and }
[[FormalParameters]] Function’s parameters
[[BoundThis]] this parameter referencing calling object
[[Call]] Only functions have this property. It’s invoked via () to internally execute function body code
[[Scope]] Scope chain. Used for closures.
[[Class]] Identifies object’s internal type. Assigned "Function"[5]
[[Construct]] Creates an object. Implemented in functions that can be invoked via the new operator such as all custom functions, and many built-in and host object functions.

[6][7]

In this post we covered the depths of functions as objects, how function objects are created, what the new operator does, and internal properties and methods used in their execution.

I’d much enjoy your comments and questions. Feel free to reach out on LinkedIn.


References #

[1] - Resig, J., & Bibeault, B. (2013). Secrets of the JavaScript Ninja (p. 32). Shelter Island, NY: Manning.

[2] Crockford, D. (2008). JavaScript: The good parts (p. 3). Beijing: O'Reilly.

[3] ECMAScript 5.1 http://www.ecma-international.org/ecma-262/5.1/#sec-13.2

[4] - Flanagan, D. (2006). JavaScript: The definitive guide (5th ed., pp. 54-55). Cambridge: O'Reilly.

[5] ECMAScript 5.1 http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.3

[6] ECMAScript 5.1 http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.5

[7] ECMAScript 5.1 http://www.ecma-international.org/ecma-262/5.1/#sec-8.6.2

 
113
Kudos
 
113
Kudos

Now read this

RabbitMQ Message Broker Patterns

RabbitMQ uses variety of asynchronous architectural patterns to decouple applications. Here we’ll cover round robin, next available worker, and publish/subscribe models, and features such as routing, pattern filtering, acknowledgement,... Continue →