Just JavaScript - The Function Object
Written by Ian Elliot   
Thursday, 01 May 2014
Article Index
Just JavaScript - The Function Object
How JavaScript implements scope
Closures & Function Statements

Closures

As the lifetime of a Function object only depends on what variables reference it, just like any other object, it can exist well after any outer function that created it. 

By the rules of nested scope the inner function has access to the variables in the outer function.

The idea of a closure simply extends this access to all times.

In other words nested scope persists beyond the evaluation of the outer function and beyond the lifetime of the outer function. 

If this wasn't the case then having inner Functions with their own lifetimes and nested scope would be very complicated.

The rule would have to be something like - an inner function has access to the local variables of an outer function but only while the function is being evaluated. If you evaluated the inner function at some later time then you could simply get an error message because variables that you could access at one time are no longer accessible. 

Using a closure means that the inner function always has access to the same variables no matter when it is evaluated. 

To be more precise a when a Function object is created all of the variables which are in scope, including those of any outer functions are stored in an execution context - this what was explained right at the start.

What is new is that the execution context stays with the Function object even when the variables no longer exist because function body which created them has finished running or the Function object that it belongs to has been garbage collected. 

As another example consider:

var myFunction= function(){
 var message="Hello Closure";  this.myInnerF=function(){
   alert(message);
   message="Goodbye Closure";
 };
};

 

The first line of myFunction creates a local variable message which is added to the execution context and set to "Hello Closure". Next an inner function is defined and a reference to it is stored in the Global variable myInnerF. The function body shows an alert box with what is stored in message and then it changes the message. This demonstrates that you can access and change what is stored in a variable that is provided courtesy of a closure. 

With this definition you can now do the following. First you can execute myFunction;

myFunction();

This evaluates the body of the function and hence results in the creation of the Function object with the function body:

 this.myInnerF=function(){
   alert(message); 
   message="Goodbye Closure"; 
 };

Notice the inner function is not evaluated this just sets up the Function object and its function body.

Now you can set the variable myFunction to null which results in there being no more references to the outer Function object and so it  is garbage collected - that is its Function object no longer exists and the message variable should no longer exist. 

Even so you can still evaluate the inner Function object. The first time:

this.myInnerF();

you will see "Hello Closure" and the second time you evaluate it 

this.myInnerF();

"Goodbye Closure" 

It seems the message variable is alive and well even if the Function object and its function body are most certainly not.

When you first encounter the idea of a closure it seems complicated and arbitrary - why do this?

Once you follow the fact that functions are just objects and a Function object can live longer than the Function object that created it you begin to see why closures are natural.

They are a natural consequence of letting an inner function access the variables of all of the outer functions that contain it. 

To make this work a Function object has to capture all of the variables that are in scope when it is created and their values when the outer functions has completed. 

This last point is subtle. 

See if you can work out what happens if we make a small change to the last example and if you can also work out why it happens:

var myFunction= function(){
 this.myInnerF=function(){
  alert(message);
  message="Goodbye Closure";
  };
 var message="Hello Closure";
};

The only change is that now message is defined after the inner function. You might reason that message isn't in scope but that would be to forget hoisting.

If you recall all variable declarations are moved by the compiler to the top of the function they occur in. So the code is equivalent to:

var myFunction= function(){
 var message;

 this.myInnerF=function(){ 
  alert(message); 
  message="Goodbye Closure";
  };
 message="Hello Closure"; 
};

This means that the variable is in scope and even though it isn't assigned to until the end of the outer function, i.e.after the definition of the inner function, its final value is part of the closure. The reason is that the execution context stores the variables and  their changing values until the outer function stops.  So the new version still displays the two messages as before.

The Function statement

In an ideal world the account of the Function object would come to an end at this point - you have enough to write any program you care to but not in a style most programmers would recognise. 

JavaScript has another way of defining a function - the Function statement. Instead of writing an assignment you simply write

function functionname(parameters){
function body
}

This results in a Function object with the specified parameters and function body being created - as before. 

What is new is the functionname. This isn't a variable but something managed in a different way. In particular the declaration of a function in this way is hoisted just like a var declaration. 

When you start a JavaScript program running, the compiler scans all of the var and function declarations and moves them all to the top of their containing function body. What this means, and this is the reason why it is done, is that you can use a function before it has been declared in the text of the program - and this is something programmers working in other languages are familiar with. 

Function names can be assigned to and generally treated like variables but they are also used by debuggers to report information on functions and how you are using them. 

Apart from hoisting and the special status of a function name as opposed to a standard variable there isn't much difference between the three different ways of creating a Function object. 

Summary

  • A Function object is a standard JavaScript object and can be used in exactly the same way as any other object. It is created using
    new Function(parameters,body)
    where parameters and body are strings separated by commas.

  • A Function object has a sort of default property - the function body, which is a String of JavaScript statements.

  • The function body can be evaluated using the function evaluation operator ().

  • It is simpler to create Function objects using either a function expression:
    var variable=function(parameters){function body}
    or a function statement
    function name(parameters){function body}
  • The key difference between a function statement and a function expression is that a function statement is hoisted.

  • A Function object can be created by the evaluation of a function body. This is often described as nesting one function inside another but it is important to realize that this nesting is really only about the way the contained function body can access variables in the containing function body.

  • Like all JavaScript objects, a Function object exists until there are no references to it when it is automatically garbage collected. 

  • Variables declared within a function are local to that function and are created when the function is executed and destroyed when it ends - but closures modify this behaviour..

  • All of the variables declared by any enclosing functions are in scope and can be accessed by an inner function body. This is called nested scope.

  • All of the variables that are in scope when the Function object is created remain accessible whenever the function body is evaluated and this includes times when the relevant variables would have been destroyed by the normal rules. This is a closure.

  • The idea of a closure is a natural consequence of using Function objects with differing lifetimes and nested scope.  

JustJavaScripticon

 

 

Just JavaScript 

 There is a newer version of the draft of the book here.

A Radical Look At JavaScript

Contents

  1. JavaScript Isn't Java, or C, or C# ... (Book Only)
  2. In The Beginning Was The Object
  3. The Function Object
  4. How Functions Become Methods
  5. The Object Expression
  6. Object Construction
  7. The Prototype
  8. Type And Non-Type
  9. Constructor And InstanceOf
  10. Duck Testing And Prototype Construction

-Preface-

Most books on JavaScript either compare it to the better known class based languages such as Java or C++ and even go on to show you how to make it look like the one of these.

Just JavaScript is an experiment in telling JavaScript's story "just as it is" without trying to apologise for its lack of class or some other feature. The broad features of the story are very clear but some of the small details may need working out along the way - hence the use of the term "experiment". Read on, but don't assume that you are just reading an account of Java, C++ or C# translated to JavaScript - you need to think about things in a new way. 

Just JavaScript is a radical look at the language without apologies. 

 

Coming Next

More functions - parameters, pass by value, expressions, methods, execution context aka this. 

Related Articles

Javascript Jems - First class functions

JavaScript Objects With Value - valueOf and toString

JavaScript Hoisting Explained       

WAT! JavaScript, Ignorance And Prejudice       

What Exactly Is A First Class Function - And Why You Should Care  

Lambda Calculus For Programmers       

The Undefined Defined Variable       

 

To be informed about new articles on I Programmer, install the I Programmer Toolbar, subscribe to the RSS feed, follow us on, Twitter, FacebookGoogle+ or Linkedin,  or sign up for our weekly newsletter.

espbook

 

Comments




or email your comment to: comments@i-programmer.info

 

Banner


JavaScript Canvas - Fetch API

Working with lower-level data is very much part of graphics. This extract from Ian Elliot's book on JavaScript Graphics looks at how to use typed arrays to access graphic data.



JavaScript Jems - The Inheritance Tax

JavaScript should not be judged as if it was a poor version of the other popular languages - it isn't a Java or a C++ clone. It does things its own way.  In particular, it doesn't do inheritance  [ ... ]


Other Articles

<ASIN:0596805527>

<ASIN:193398869X>

<ASIN:0137054890>

<ASIN:1449381871>

<ASIN:1430230541>



Last Updated ( Sunday, 10 May 2015 )