JavaScript the Weird Parts

Amaury Larancuent
31 min readMay 17, 2021

Definitions to Start

Syntax parser: is part of JavaScript engine. It reads your code character by character, tells what your code does, and checks if the grammar is correct. You can think of the syntax parser as an interpreter between your code and computer. It translates your code to machine readable code.

Execution context (EC) is defined as the environment in which the JavaScript code is executed. By environment, I mean the value of this, variables, objects, and functions JavaScript code has access to at a particular time.

Execution context in JavaScript is of three types as:

  1. Global execution context (GEC): This is the default execution context in which JS code starts its execution when the file first loads in the browser. All of the global code i.e. code which is not inside any function or object is executed inside the global execution context. GEC cannot be more than one because only one global environment is possible for JS code execution as the JS engine is single threaded.
  2. Functional execution context (FEC): Functional execution context is defined as the context created by the JS engine whenever it finds any function call. Each function has its own execution context. Functional execution context has access to all the code of the global execution context though vice versa is not applicable. While executing the global execution context code, if JS engine finds a function call, it creates a new functional execution context for that function. In the browser context, if the code is executing in strict mode value of this is undefined else it is window object in the function execution context.
  3. Eval: Execution context inside eval function.

Lexical Environments: Where something sits physically in the code you write. It’s location in the js file. Where (above/below, linkage) code is written matters.

Name/Value pair: a name that maps to a unique value. A name may be defined more than one, but can only have one value in any given context. The value may be more name/value pairs. Objects are just nested values of name/value pairs.

The Global Environment and the Global Object: The base execution context is your Global Execution Context (GEC/ JavaScript Engine). The GEC builds two things: 1) a Global Object (name/value pairs), and a variable named ‘this.’ In browsers, the Global Object is the Window object. (Global here means “not inside a function”. Your variables and your functions not attached to anything will be assigned to the Global Object (window for browsers)).

The outer environment is the execution context above the one the code is executing in. There is no outer environment for the Global Execution Context. These are the parts of an execution context (check that global exists in all execution contexts).

The Execution Context — Creation and Hoisting:

Above we see code and the output of running that code in the console. In the first example we see what we would normally expect to see. A variable and function declaration, and then the use of the function and variable after, resulting in the expected results. In the second we move the use of the function and variable above their declaration an error (something refereeing to the fact that a and b are not yet defined. Instead we see that the function is available, and that the variable is assigned a value of undefined. In the third example we remove the variable declaration, to show the ReferenceError and establish that the variable is being assigned a value before its assignment in the lexical environment.

This assignment of undefined to variables before they are explicitly assigned lexically is often called hoisting.

The Execution Context is created in two phases: 1. The creation phase, and 2. execution phase.

The following is created during the creation phase:

We see that the Global Object, this and the Outer Environment are all created, but we also see the JaveScript engine run through the code and set up memory space for variables and functions. The entire function is stored in memory during this pass, and only the memory placeholder for the variable is stored. This placeholder has the value undefined. When the code is actually run line by line, after this initial pass, then and only then are variables assigned their value as written.

JavaScript and Undefined:

We see here that undefined is a variable in JavaScript, like null. Never set a variable directly to undefined. It is more helpful to rely on the JavaScript to set the variable to undefined during the creation phase to determine if you assigned a value to the variable or not. This will help more during debugging.

The execution phase uses all the things created by the creation phase, then runs your code line by line:

Single Threaded Synchronous Execution: Single threaded means that one command is executed at a time (kind of like python, see if something like the GIL exists for JavaScript (I don’t think so)). Synchronous means, again, one at a time, and in order. Basically the execution phase of the Execution Context will be a single threaded synchronous execution, running each line one at a time, and in order.

Function Invocation and the Execution Stack

Functions are invoked, run, by using the parenthesis () after the function name, assuming it has been declared and hoisted into memory.

When the functions above are run, a Global Execution Context is created, and then executed. The function a is the invoked, and an entirely new execution context is created for that function and placed on the execution stack “above” the Global Execution Context. Function a’s execution context is then executed, and function b is invoked, creating yet another execution context “above” that of function a’s on the stack. Once function b is finished, its execution context is removed from (popped off) the stack, and the function a’s context is then the focus and allowed finish execution. Once finished function a’s context is removed from the stack and we are back to the Global Execution Context.

Functions, Context, and Variable Environments

Variable environments are where the variable live — their scope, where they are seen, and lifecycle, when they are created and destroyed. Every execution context has it’s own variable environment.

myVar in each execution context on the execution stack is a unique variable in the above case. Here we see a code example and the results on the consile

The Scope Chain

The code above defines two functions b and a, declares and initializes a variable called myVar and then invokes function a. Function a re declares and initializes the variable, and invokes function b. Function b simply logs the value of myVar; what is the value of myVar in function b?

The value the console shows us is 1, why? We know that the creation phase of the execution context creates a reference to the outer environment. One would think the outer environment should be function a, since function a invokes function b, but this is not the case. The outer environment is determined by the function’s lexical environment, where the function was written. In this case function b sits in the Global Context lexically, so its outer environment is the Global Execution Context. If it was written in function a, then function b’s outer environment would be function a’s execution context.

We have changed the lexical environment of function b above. We have placed it lexically inside function a. Now the function cannot be called in the Global Execution Context because it doesn’t exist there (it exists only in function a’s execution context), se we get a ReferenceError when we try to call function b from the Global Execution Context.

The value of myVar is now two in function b’s execution context. The outer environment of function b’s execution context is now function a’s execution context, as function b was defined lexically inside of function a. The new scope chain is shown below.

Scope, ES6, and let

Scope is where a variable is available in your code, where it can be seen. If the variable has the same name in the scope chain, which value does it have in it’s scope.

let and var are two ways to declare variables. Unlike var, we are not allowed to use the variable declared by let, until after the line of code that declares the variable. Also, unlike var, the variable is destroyed after the block is executed. A for loop, for example, would have a new variable for each iteration. This is called block scoping. Blocks are usually defined by the curly braces.

Asynchronous Callbacks

Asynchronous: more than one at a time

The browser contains other pieces aside from the JavaScript engine. The browser will also contain, for example, the rendering engine and the engine that controls HTTP requests. These are separate from the JavaScript engine and can be called to run outside of it. So even though the JavaScript engine runs single threaded synchronous execution, calls to other engines appear to happen asynchronously (callback functions, promises, etc).

On top of the execution stack there is something in the JavaScript engine called the event queue. Here is where events are stacked by the JavaScript engine when it encounters them in the code. An event is only taken off the event queue when all the execution contexts spawned by the Global Execution Context are taken off the event stack (execution is complete). When an event is taken off the event queue a new execution context is created for its callback function, and the process continued.

Results without clicking the mouse
Results with clicking the mouse. The event is handled after the global context is done

Types and JavaScript

Dynamic typing (vs Static typing): the JavaScript engine determines the type of the variable at run time (usually during initialization, would be my guess, but double check). This is done during the execution phase.

Primitive type: a type of data that represents a single value. That is not an object.

There are six primitive types: 1) undefined (don’t set a variable to this purposefully, it is used by the JavaScript Engine), 2) null (use this instead), 3) boolean (true or false), number (floating point. only one number type in JavaScript. makes math weird), string (sequence of characters. ‘’ or “”), symbol (used ES6).

Operators

Operators are special functions that is syntactically different. Generally, operators take two parameters and return one result.

The plus sign is an operator that takes 2 numbers and returns their sum. This is infix notation (look up), where the operator is between the parameters. Prefix notation would be something like lisp, and postfix is a lot like some financial calculators where you press the function at the end.

Operator precedence and associativity determine which order the operators get called in when there is more than one in a statement. Precedence defines which operators have precedence and are called first, associativity defines which direction has precedence left to right or right to left when operators have the SAME precedence. Each operator has its own associativity, precedence is determined by the JavaScript Engine.

Associativity of = (assignment) is right to left, so everything is 4

Coercion: converting a type from one type to another. This happens a lot in JavaScript as it is dynamically typed. Coercion happens when operators that are called with two different types. Usually one type is coerced into another to make the operator return a semi coherent value.

Comparison Operators

The first example works as expected, the second does not, why? First check associativity. > has an associativity from left to right, 3 < 2 is evaluated first. The equation becomes:

Now the < operator must coerce one of these parameters to the type of the other. It choses the boolean value false and coerces it to the number 0.

And this is true. Remember associativity, precedence and coarsen, please. The JavaScript Engine decides, for example:

These should be similar, but they are coerced into different Numbers. But when using the equality operator, ==, null != 0, but null < 1 is true. Comparison operators need to be checked at all times. The ===, triple equals, or strict equality, doesn’t try to coerce any of the parameters. If they two parameters are of different types, === returns false.

Existence and Booleans

All of these things that imply the lack of existence, emptiness, and nothingness all define to false:

We may not 0 to be equal to false, if we are doing a check for nothing (if(a){}, for example). So, if (a || a === 0), since === has higher precedence than || and will be run first. But one can see how easy it is to check for nothingness in JavaScript.

Default Values

what happens when the name parameter is not provided and is defaulted to undefined? Here we set a default vaule of ‘<Your name here>’. The || operator returns the value that coerces to true.

Framework Aside: Default Values

When js code is add like this, this basically stacks the code in each file in order and runs it as though it was one file. To avoid conflicts, use the || operator as above:

Objects and Functions

Above we described objects as nested name/value pairs, for example:

In memory, an object has an address, and can have references to primitive types, or other objects, which are called properties, as well as references to functions, which are called methods, for example (each hex number represents a memory address):

The two ways to create and access objects are shown on the operator precedence table:

Computed Member Access, or [], and Member Access, or the dot, or “.”. Member Access has a higher precedence than Computed Member Access, but both are near the top of the precedence table.

There are several ways to create an object, but we will start with the most obvious. There are “better” (more preferred) ways, but this is a good place to start. We see that we can get and set the properties of new objects with either operator. The preferred method is the Member Access operator, or the “dot” operator.

Another way to create a JavaScript object is the object literal. This:

produces an object in memory. As does this:

The second way is called an object literal, and is depicted in syntax as curly braces (not attached to a function declaration or if or for statement). These objects can also be initialized with some properties, as shown:

This is faster than creating a new Object() and then adding the properties one at a time using either the Computed Member Access or Member Access operators. We see we can create nested objects as follows:

We can also use object literal syntax where ever we would use an object variable, like, for example, passing a parameter to a function:

Faking Namespace: A namespace is a container for variables and functions that is associated with a unique name. A module (file) path is sometimes used. JavaScript doesn’t have namespaces, but we can fake it by putting the functions and variables in objects.

JavaScript Object Notation (JSON): similar to object literal syntax, but there are important differences. For example, property names have to be wrapped in quotes in JSON (this is optional in object literal notation).

JSON is a stricter form of object literal notation, as it has more rules. We can use the JSON object in JavaScript to convert one to the other.

First Class Functions are objects and everything you can do with an object, any type actually, you can do with a first class function. Assign them to variables, pass them around as parameters, return them from other functions, and create them on the fly are some of the benefits of programming languages with first class functions.

The Function Object: One should think of a function as an object that is like any other object with two special properties: name (optional) and code, which is invokable with the () operator.

Here we see how we can add a primitive parameter to the function:

Function Statements and Function Expressions

Expression: unit of code that results in a value (it doesn’t have to be saved to a variable)

Statements: units of code that don’t return a value (if, for, etc). Statements just do work.

Function Statement:

This is a function statement. It has some special help from the JavaScript Engine in that it is hoisted, so exists in memory during the creation phase of the execution context. It is during this phase that the function object is created and its name and code properties are set.

Function Expression:

This is a function expression. It returned a value and was assigned to the variable anonymousGreet. Here is the object representation. The name property is not set (there is nothing between function and the ()), but that’s fine as it was assigned to a variable and the variable points to its location in memory. We use the variable to invoke the function.

You can use function expressions as parameters to other functions, and then invoke them with the parameter name and the () operator.

For primitive types, assignment, which includes passing as a parameter to a function, is by value:

For objects, all assignment is by reference:

By value:

By reference:

Here is a special case for objects being created with object literal notation:

Objects, Functions and ‘this’

When a function is invoked (using the name/variable name and the () operator) a new execution context is created. As a reminder:

At the global level, the Global Execution Context has defined ‘this’ (in the browser, the global object is the Window object):

If you are simply invoking the function in the global execution context, then this will also point to the global object. Three execution contexts (global, function a’s and function b’s), and ‘this’ points to the global object in all three. You can even add a parameter to the global object in one function’s execution context and then access it as a global variable in the global lexical environment (I assume this is bad form, lol):

What is this in an object method?

‘this’ is now pointing to the object to which the method belongs (in this case c). We can also update the parent object in the function call.

What happens when we create a function within an object method?

bottom one second run of new code, shown as same as first run, no change was made to the object when setname was called, so the ‘this’ is something different than the parent object, what is it?

But in the global object we see the change!

Opening the window object in the console. Scroll down and see the values below

Some people think that this is weird behavior. It is what it is. This is what happens in JavaScript and this needs to be remembered.

Interesting way to combat this, use a placeholder called self at the top of the function’s lexical environment and use it throughout. The scope chain will ensure that this self is used at all times:

Now they are different, yay!

Arrays

‘arguments’ and Spread

When a function is invoked an execution context is created, he is a more accurate picture of this than we have seen:

The ‘arguments’ keyword contains all the parameters passed into the function.

Here we see the parameters don’t have to be passed, they are automatically set as undefined when the execution context is created.

This works! No errors, all you will see is a lot of undefined in the console, until the last call when all parameters are defined
setting up a default parameter before ES6, now you can just add it to the parameter list in the function decleration
Last call for greet above with the line above added. Shows how the arguments look like. They are considered “array like”

Look up spread and how it’s done in ES6, but the same idea applies, just different naming conventions

Syntax Parsers: an intermediate program that translates your code into something the computer can understand. The JavaScript engine does this.

The syntax parser in JavaScript does something called Automatic Semicolon Insertion. If you have a statement that has a carriage return where a semi colon should be, the syntax parser will inject a semi colon there

becomes

So this:

produces this

because the JavaScript engine inserted a semicolon like this

Don’t put the object literal on a different line, do this instead:

And anywhere you think a semicolon should go, put it there.

Whitespace: invisible characters that create space in your code. They make code more readable to the human eye. Carriage returns, tabs and spaces. The syntax parser is very liberal in how it handles white space (it pretty much ignores it)

Immediately Invoked Function Expression:

This will return a string, obviously.

Above we see a JavaScript pattern. first we see a function expression inside (). Without the () this would error out as the syntax parser would think this was a function statement without a function name. The () allow the function expression to stand alone in memory. We can then invoke this expression using () after the function expression (can even be after the enclosing parens), and pass it a parameter.

IIFE and Safe Code:

Above we see that the function is created as an anonymous function in the global object. When the function is invoked (immediately after it is created) a new execution context is created for the anonymous function. All variables declared inside the function do not collide with the global object at all. They are in a “safe” zone. Any code called in this function will not interfere with any code for it is encapsulated within its own execution context.

If you wanted access to the global object, you could do this

Here you are affecting the global object intentionally, so this is deemed safer.

Closures:

There are two variables in the function buildFunctions, i and arr. The key is to think “what are the values of these two variables when the array is returned? What is in the function’s execution context?” The answer is arr = [f0, f1, f2] and i = 3.

Same is true for fs[1]() and fs[2]()

To “fix” this issue, ES6 uses the let syntax. But if you don’t have access to ES6, you can use the following coding pattern:

Because you are invoking the function immediately, you are creating a new execution context each time i is passed as a parameter. This new execution context is what will create the closure encapsulating the value of i as it is seen in the for block (mimicking the let keyword and block scoping). One can reverse engineer this. All one has to do is say I need to push a function with it’s own execution context. This is a IIFE! This execution context needs to wrap a function so that function can use the variables in that execution context and this is done by having the function return a function.

Function Factories

A function that uses a parameter (in this case language) to create a function who’s return value depends on that parameter (aka a function factory), using closures.

Closures and Callbacks

Here we have a function, setTimeout, that takes a callback function as a parameter. We see the callback created via a function expression and passed as the first parameter to setTimeout. This callback function is using the variable greeting created in its parent function (sayHiLater). This is a closure, as sayHiLater finishes execution before the callback is called (the callback is called after three seconds from execution, so some time has elapsed between sayHiLater finishing execution and the execution of the callback function).

Callback Function: A function you give to another function to be called when the latter function is finished. Building a simple callback function (all it is using a function as a parameter and then invoking the function parameter with the () operator.

call(), apply() and bind():

bind() returns a function with this set as the first parameter passed.

This also works

call() calls the functions, same as the () operator, but the first parameter is object this will point to, and the remaining objects are parameters to the function being called:

apply() does the same thing as call(), but if you try this, you get an error:

Because the apply() method wants an array of parameters

Otherwise, it is the same as call().

To beat the dead horse of the IIFE and “safe” code, one can also do this:

Thus passing the object one wants to define as ‘this’ in the IIFE ‘safe’ zone. It could technically be the global object (by simply passing this in the apply function), but this would destroy the safe zone, lol.

Function Borrowing:

Here we see an object, person2, with no function called getFullName, use apply to “borrow” getFullName from the person object.

Function Currying: creating a copy of a function, but with some default parameters

This is similar to partial in python’s functools module. bind() returns a function with this set to the first parameter, but the subsequent parameters are parameters of the function calling bind and can be set permanently, as shown. The function returned by the bind() call will always have this set to the global object (unwise, lol) and 2 as the first parameter, aka a. The two multipleByTwo are essentially the same function (produce the same outputs for any given input).

Functional Programming

How do we make the following functional:

Because functions are first class in JavaScript, we can do something like this (where fn is a multiplyByTwo type function):

or

You can map whatever function you like as long as it takes in one parameter (the array item) and returns one value.

Using bind(), you can abstract away even more functionality easily:

If you want to encapsulate the bind() call:

Underscore.js

Object Oriented JavaScript and Prototypal Inheritance

Classical vs Prototypal Inheritance: Inheritance is when one object gets access to the property and methods of another object. Classical inheritance is as it’s done in C++, Java, C#, etc

This is propaganda from the course:

Understanding the Prototype

All objects have a property called proto. Proto is just a reference to another object and can stand on its own as an object. This proto property establishes a chain of reference. If one requests a property from an object using the . (dot) operator, and that property doesn’t exist in the object, the proto object will then be checked for that property’s value. The proto object can itself have a proto object and this establishes a prototype chain. Any object can point to the same prototype.

Don’t use this method as it will lead to performance problems (research why)

We see here that this is automatically referencing the object that made the call, and not the original object (which would have shown ‘Default Default’).

Seeing the prototype of base objects, which provide the base methods we have used above.

Reflection and Extend

Reflection is when an object can look at itself, listing and changing its properties and methods. In JavaScript this can be achieved with the following

This will not only grab items in the current object(john), but also in the prototype (person). If you only want the properties of the current object (john), and not the prototype (person), then do this

Extend is a function, usually created in JS libraries, not provided by JS itself, that allows you to add the properties of other objects to a target object (usually the first argument in the extend function)

Here the john object now has all the properties in jane and jim.

Here is the implementation in underscore.js. We see it using reflection to implement extend.

Building Objects

Function Constructors, ‘new’ and the History of JavaScript

When JS was created, it was trying to attract Java developers and so called it self JS. It also had syntax like this

This is a function constructor: a normal function used for constructing objects using the new keyword.

The new keyword, is actually an operator.

When we use new, an empty object is created (same as {}). It then calls the function constructor(Person). When the function constructor is called it creates an execution context, and points the ‘this’ variable of that execution context to the empty object. So all calls to this in the function constructor are now impacting the empty object and “constructing” it. As long as the function constructor doesn’t return a value, it will return the object created by the new operator. You can add parameters to the function to add flexibility to object creation (same as any object constructor in any language).

Looking at the prototype of the new object we see

All functions have a property named prototype that is only used by the new operator. This is not the same as the __proto__ property.

The new operator creates an empty object that is set to the this variable in the function constructor’s execution context, manipulated by the function constructor, and then returned as the return value of the function constructor (if no return statement is found in the function constructor). The prototype of this object is set to the ‘prototype’ property of the function constructor. Essentially:

So now this is possible

And all objects created with the function constructor would have access to this method. It saves space since putting the function in the function constructor itself would mean each object would have a copy of that method. Now the only copy of the method is in the prototype. Using this logic, one can use the prototype to create class/static variables as well.

Dangerous Aside: new and functions

The above is calling the function constructor without a new keyword. If the function constructor doesn’t return anything, then the variables john and jane will be set to undefined, and nothing will work properly. What’s worse is that the variable this in the function constructor will be pointing to the this of whatever execution context it was called. This could be global or some other function, but either way this is not good.

To help with this function constructors are using created with a capital letter to indicate that a new keyword should be in front of any call to a function constructor.

Built-in Function Constructors

There are built in function constructors for primitive values and have some extra functionality. The primitive types have access to the prototypes of these built in function constructors, so you can add functionality to all strings by adding it to the String.prototype object.

This, however, doesn’t work for numbers

Dangerous Aside: Built in Function Constructors

a and b are not the same type, so the last one is false. The == coerces types, the === does not (check if this is correct). This can cause problems when comparing values, so one should be consistent always, and should probably use literal primitive values instead of the the built in function constructors consistently.

For work on dates, use momentjs

Dangerous Aside: Arrays and for … in

If we loop through an array using for … in, we see this

An array is an object and this object has properties. The property names are the numbers 0, 1, 2 and the property values are the values of the array John, Jane, Jim. If we add a property to the Array prototype (which is what the [] operator is calling when used), we see this

So when iterating through arrays, use the following to avoid iterating into the prototype

Object.create and Pure Prototypal Inheritance

Objects don’t create execution contexts, so if you forget a this in an object literal, it will cause errors as the method using this will be looking in the wrong place. Always add this when creating methods in object literal syntax and referencing another property.

What does the above code create?

We see that john is an empty object (has no properties of its own), but its prototype is the object passed into Object.create(). So now one can add and/or override whatever properties one chooses

And have access to all the methods in the prototype object

What if you don’t have access to a JavaScript engine that has access to Object.create? We can use a polyfill. A polyfill is code that adds a feature which the engine may (or may not) lack.

This creates an empty function (F), sets the prototype property of the function constructor to object passed as a function parameter, o, and then returns the object returned by the new operator. Put this atop any file in the browser and Object.create will be available.

ES6 and Classes

Here we see the use of the class keyword and the new keyword together. We think of class as a template that is used to create objects in other programming languages. In JavaScript a class is an object. To set the prototype, one does the following

super() calls the constructor of the prototype.

Odds and Ends

Initialization

--

--