Tuesday, May 6, 2014

Noobs Guide To Java Script

Hello and welcome to the NOOBs guide to JavaScript. First let me start by saying that this series is not going to show you hot to change the mouse cursor, how to animate letters and similar circus tricks. There are plenty of such tutorials out there. Instead I'll try to teach you how JavaScript programs actually work, but without going into too much technical details.

OK so this is not the first article out there trying to explain this subject. However while reading all the other articles I noticed that it usually took me more than one reading of the text until I could fully understand what the author wanted to say. Any yes, that might be explained by me being stupid on not understanding the English lingua. However I'm willing to bet that I can write a text will make things clear in only one reading.

There are of course other motivations for writing this series, such as that writing helps me focus and remember complicated and/or boring things... and serves as a quick reminder after a while, when things start to fade away.

The text you are about to read is not a technical manual. I'ts purpose is to explain the principle and not cover all the technical details. With that goal in mind it's structured and written in a way which is easy to follow. Each time a new JavaScript language construct is mentioned I will cover just the parts relevant at that moment, so that the line of thought is easier to follow. Some of the stuff you'll run into may not be the best example how things should be done in real life - just think of them as a teaching tools.

There are a lot of examples showing how something works in code. Don't hesitate to try them out, try changing something, play with it a bit ... it will help you get the feeling for the stuff.

Part 1 - Code Execution

How JavaScript engine prepares and executes programs may seam to you a bit too low level at first, however understanding it will help you avoid some of potential bugs.

Code execution basics

There are three ways code can be included in a web page:
  • directly in the HTML page itself
  • linked from the external JavaScript file
  • via the eval() function at run time
The browser will run all the code in the order in which the code was listed in the HTML page, regardless which of the methods was used. The code execution begins as soon as the code becomes available. Let's see an example:

<html>
    <head>
        <title>NOOB JavaScript guide</title>
        <script type="text/javascript">
            document.write("inline code 1");
        </script>
        <script type="text/javascript" src="externalScript.js"/>
        <script type="text/javascript">
            document.write("inline code 2");
        </script>
    </head>
</html>

Here's the code inside the externalScript.js:

document.write("external code");

When this file is loaded, here's what will happen:
  • the HTML document is loaded
  • "inline code 1" is written to the document
  • browser starts to load externalScript.js
  • when the loading of the external script file is finished, the code inside is executed
  • "external code" is written to the document
  • "inline code 2" is written to the document
  • execution
As you can see the execution of the 2nd inline code is delayed until the code in the externalScript.js is loaded and executed.
If more than one JavaScript external files is linked to the document, the documents are loaded and executed in the same order as they were listed in the HTML code.

You can think of this as if the browser loads and inserts the code from the external file into the HTML document at point in which the file was linked. So in the end all the code is contained in the same document and executed.

This has one important consequence: if one of the external JavaScript file takes long time to load, execution of all the code which follows will have to wait until the file is fully loaded and executed.

Program level code

The term "program level code" is used to describe code which isn't contained in any function or expression. This kind of code is executed as soon as it is loaded, in contrast to code inside functions, which is executed when the function is called.

All the variables or functions declared at program level live in the global scope. Let's see an example:
<html>
    <head>
        <title>NOOB JavaScript guide</title>
        <script type="text/javascript">
            var programLevelVariable = 10;

            document.write("running at program level");

            function programLevelFunction()
            {
                var localVariable = 20;
                document.write("running at function level");

                function localFunction()
                {
                    document.write("running at function level);
                }
            }
            
            programLevelFunction();

        </script>
    </head>
</html>

Execution stages

Now we know the basics, let's say something about how actually is executed. Every time a function (or any new piece of code) needs to be executed, the execution is done in two stages:
  1. context stage
  2. code execution stage
Before executing any code JavaScript engine first prepares code to be executed. This is called Context Stage, since at this point the Execution Context (explained in he part about the variables) is created and initialized:
  • the Variable Object is constructed and filled with
    • function parameters
    • variables - at this stage values are set to undefined
    • function definitions
  • scope chain is prepared
  • this value is set
After the context has been created, the code is ready to be executed - we enter the code execution stage.

One effect of code being prepared first and then executed is that we can call a function before it has been defined in code. This works only for Function Definitions, which are discussed in the part about functions. For example the following works:

myFD("show this text"); // this works -> Function Definition

function myFD(message) {
  alert(message);
}

myFE("show som other text"); // this doesn't work -> Function Expression

var myFE = function(message) {
  alert(message);
}

Execution Context - continued

The Execution Context was mentioned in the part about variables, before a lot of other concepts were introduces. Now is the time to say something more about it. As said previously Execution Context packs together all the information about the code currently being executed or which is about to be executed. It is constructed at the context stage, and is in a way a starting point from which the code execution starts.

The following picture shows this object in more details:
Part 2-

Variable Object

In every program we write we bill probably need to use some variables (and functions). As you probably know variables are stored in memory and can be assessed by the variable name. Variables are stored in a collection of key-value pairs.

But wait a minute! This sounds familiar! Isn't that the definition of the JavaScript Object (see part 1)!? That's exactly right!
That's why the object in which variables are stored is called Variable Object = VO.

But the VO is not only the storing place for variables, but also for FDs (Function Declarations and function parameters. So let's see an example:

var a=10;
var b=20;
var c="some text";

function myFD(param) {
    alert(param);
}

Here's what the VO for the above code would look like after the code was executed:

Execution Context

So now we know where the variable values are stored. However having a single VO in the entire program would lead to variable name collision. Each variable declaration would need to use a different name. To solve this a new Variable Object is constructed each time a function is about to be executed and is used for storing variables declared within that function.

This new VO is stored in what is called Execution Context - it's an object which packs together all the information (context) about current state of code being executed.

Execution Context contains much more than just Value Object ... but let's leave that for later.

Scope Chain

Although variables defined within the function cannot be accessed by the code outside the function, the code inside can access all the variables defined outside. This works because of scope chain.

All the functions in JavaScript are nested one within another, thus creating a hierarchical structure. For example:

var globalVariable = 10;

function outerFunction() {
    
  var outerFuncVar = 30;

  function innerFunction() {
    var innerFuncVar = 30;
  }
}

Scope chain is a list assigned to an Execution Context, which contains a list of all value objects within the nested hierarchy. For the above example this would look something like:


When accessing a variable, JavaScript engine starts by searching the VO of the current scope. If the variable is not found it then continues to search the next VO in the scope chain etc. So for example if the innerFunction() tried to access the globalVariable here's what hapens:
  • VO3 is searched -> variable is not found
  • VO2 is searched -> variable is not found
  • VO1 is searched -> variable is found and the value returned
If the variable isn't found after searching VO1 (global Value Object), the value of undefined is returned.

Part 3-



No comments:

Post a Comment