Core Theory and Programming Patterns




Navigate with keyboard arrows in all directions.
Use the control on the bottom right part as page availability hint.

Content

1. Core Theory

  • Create Data
  • Read Data
  • Update Data
  • Delete Data

2. Programming Patterns

  • General Patterns
  • Function Patterns

Content Motivation

Why C R U D operations as backbone for core theory presentation?



  • We need applications to manage data
  • C R U D is all about data
  • Programming Language = in-memory C R U D operations

Create (R U D)

How to introduce data into your system...

Mozila Reference:

You use variables as symbolic names for values in your application. The names of variables, called identifiers, conform to certain rules.
  • Cluttered with too many terms -> variables, names, identifiers
  • It is better to stress on the fact that we have a mean to access data (identifier)
  • ... rather to stress on the fact that we are able to change this data (variable)
  • So I prefer the term 'identifier' for theory explanation!

What About Object Creation?

  • We create objects via variable declarations
  • var obj = {prop: ‘propValue’};

  • Property names refer to data but they differ from identifiers in their resolution strategy

Summary

The only way to create data is with:

  • Variable declarations
  • Function declarations

The Importance Of Thinking In Terms of Identifiers

var Object = function () {
	this.prop = "propValue";
};
var obj = new Object();
assertEquals("propValue", obj.prop);
						

Always think to what your identifier is pointing to!

In our example 'Object' identifier points to different function not the built-in provided by JavaScript

(C) Read (U D)

How to find your data...

JavaScript code is executed in a context - execution context (EC)

  • By default we are runing code in a context called Global Context (GC)
  • Understanding data resolution means understanding execution context

How to create context different from GC?




A: The (almost) only way to create a new context is to invoke JavaScript function!

What is the purpose of having Execution Contexts?




A: To manage data visibility

How these rules are achieved internally?




A: Try to understand the Execution Context structure

Dynamic Scope Array - 'With' Statement

//Scope = VO.scopeArray

var x = 10, y = 10;
with( {	x : 20 } ) {

	//Scope = withObject + VO.scopeArray

	assertEquals(x, 20);
	assertEquals(y, 10);
	var x = 30, y = 30;
	assertEquals(x, 30);
	assertEquals(y, 30);
}

//Scope = VO.scopeArray

assertEquals(x, 10);
assertEquals(y, 30);
					

Dynamic Scopes - Catch Clause

try {
  ...
} catch (ex) {
  
  //Scope = catchObject + VO.scopeArray
  
  alert(ex);
}

A catch clause creates temporary scope object 
with single property.

var catchObject = {
  ex: {exception object}
};
				
					

Question 1

alert(p); // ?

var p = 5;

alert(p); // ?

var p = 6;

alert(p); // ?
					

Question 1 Answer

alert(p); // undefined

var p = 5;

alert(p); // 5

var p = 6;

alert(p); // 6
					

Conclusion After Question 1


All declarations are moved (hoisted) on top of the context


With other words: All identifiers are created during context creation

Question 2

alert(typeof x); // ?
		 
var x = 10;

alert(x); // ?
		 
x = 20;
	 
function x() {};

alert(x); //?
					

Question 2 Answer

alert(typeof x); // function
		 
var x = 10;

alert(x); // 10
		 
x = 20;
	 
function x() {};

alert(x); // 20
					

Conclusion After Question 2


Identifiers created as a result of function declaration gets their values at context creation phase

Question 3

function test() {
	foo(); // ?
	bar(); // ?
	var foo = function () { 
		alert("foo");
	};
	function bar() { 
		alert("bar");
	}
}
test();
					

Question 3 Answer

function test() {
	foo(); // TypeError "foo is 
	          not a function"
	          
	bar(); // "bar"
	
	var foo = function () { //FE 
		alert("foo");
	};
	
	function bar() { // FD
		alert("bar");
	}
}
test();
					

Conclusion After Question 3


Make difference between Function Declarations and Function Expressions


Identifiers that points to functions created with expression gets their value at Context Execution Phase

Function Expressions Definition

Defines a function as a part of a larger expression syntax (typically a variable assignment, callback etc.):

var f = function() {};


Anonymous FE does not introduce identifier because they do not have name!


Named FE introduce identifier visible only in the context created by NFE itself

Named Function Expressions

var test = function test1() {
   //test1 is valid identifier here
};
//test is valid identifier here
//test1 is NOT valid identifier here
						

In Some IE versions test1 could be leaked into the parent context

Best Practice: var f = function f() {};

Very Recommended Readings About Functions By The Following Authors:


Dmitry Soshnikov


Angus Croll


Juriy Zaytsev

And now the most essential part...

Function Created With Function Constructor

var x = 10;
 
function foo() {
 
var x = 20;
var y = 30;

var foo = function () {alert(x); alert(y);}; 
var bar = new Function('alert(x); alert(y);');
 
foo(); //20, 30 
bar(); // 10, "y" is not defined
 
}
					

Eval Example

var y = 100;
function f() {
	var y = 10;
	alert(y);
}
f(); //10
alert(y); //100
						
var y = 100;
eval('var y = 10; alert(y)'); //10
alert(y); //10
						

Eval Facts

Eval Creates New Execution Context


Eval Augments The Calling Context


In the strict-mode of ES5, eval already does not influence the calling context, but instead evaluates the code in the local sandbox.

Data Resolution Summary

  • Think in terms of identifers ... are they available or not ... from which context they are resolved

  • Respect the lifecycle phases - EC (Creation, Execution),Function (Creation, Activation, Execution)

  • Make difference between functions created with declaration, expression, and new Function contructor
  • Be careful with eval or just do not use it
  • Closures In EcmaScript

    Dmitry Soshnikov:

    So if you completely understand the [[Scope]] and a scope chain topics, which in detail were discussed in the chapter 4, the question on understanding closures in ECMAScript will disappear by itself.

    Closures General Theory

    Funarg: Function used as function argument

    the anonymous function is funarg

    exampleFunc -> Higher Order Function

    function exampleFunc(funArg) {
    	funArg();
    }
     
    exampleFunc(
    	function () {
      		alert('funArg');
    	}
    );
    						

    Closures General Theory

    Function Valued Functions: Functions that return other functions

    (function functionValued() {
      return function () {
        alert('returned function is called');
      };
    })()();
    						

    Closures General Theory

    First Class Functions: Can be passed as arguments and returned from other functions

    In EcmaScript all functions are first class

    One [[Scope]] for all closures per context

    var firstClosure;
    var secondClosure;
     
    function foo() {
     
      var x = 1;
     
      firstClosure = function () { return ++x; };
      secondClosure = function () { return --x; };
     
      x = 2; 
     
      alert(firstClosure()); // 3
    }
    foo();
    alert(firstClosure()); // 4
    alert(secondClosure()); // 3							
    						

    Closures Summary

    All functions, independently from their type - function expression (anonymous, named) or function declaration - are closures!


    Exception is Function created with Function constructor which scope contain only global object


    From the practical viewpoint those functions are interesting which are:

    1. passed as arguments and uses free variables
    2. returned inner function (continue to exist after their parent context is finished)

    (C R) Update (D)

    Am I actually updating my data?

    References To Immutable Objects


    What do we do when we need to change the object?

    In many languages it is used Copy-on-write(COW)


    Clone the object it points to

    Change the pointer value

    Proceed with mutation

    ...but not in JavaScript


    There is no way to modify a string

    str.concat('modification') doesn’t modify str at all, it returns a new string with the replacement executed.

    (C R U)Delete

    Deletion is still possible :)

    Example 1

     
    var o = { x: 1 };
    delete o.x; // true
    o.x; // undefined 
    						

    Example 2

     
    var x = 1;
    delete x; // false
    x; // 1
      						

    Example 3

     
    function x(){}
    delete x; // false
    typeof x; // "function"
       						

    Why do these examples work like that?



    A: Understand the difference between identifiers and properties.
    See next...


    Identifiers VS Properties

    Identifiers (indirect property creation):

    • Variable And Function Declaration Creates Identifiers
    • The identifiers become properties of Variable Object


    Properties(direct creation):

    • Object property declaration -> var obj = {x: 5;}
    • Undeclared assignments (no var) -> x = 5, creates property on the GO
    • Properties does NOT become properties of the Variable Object

    Both the identifiers and the properties have properties

    ReadOnly

    DontEnum

    Internal

    DontDelete


    - Identifiers have DontDelete property set to true

    - Properties have DontDelete property set to false

    Delete operator checks "DontDelete" property to decide what to do

     
    var o = { x: 1 };
    delete o.x; // true -> x is property and its 'DontDelete' property is false
    o.x; // undefined 
    						
     
    var x = 1;
    delete x; // false -> x is identifier and its 'DontDelete' property is true
    x; // 1
      						
     
    function x(){}
    delete x; // false -> x is identifier and its 'DontDelete' property is true
    typeof x; // "function"
       						

    Be careful with Firebug

    var x = 1;
    delete x; // true
    x; // undefined
    						

    - Firebug execute the code in Eval statement

    - Declarations inside eval does not set DonDelete to true

    Complete Resolution Strategy

    Identifier (Data) Resolution:


    - Search in: own AO, parents AO, GO, GO.prototype

    //Yes it is searching in GO.prototype as well							
    function foo() {  alert(x); }
    Object.prototype.x = 10;
    foo(); // 10							
    						

    Property (Nested Data) Resolution:

    • Search in prototype chain
    • It involves identifier resolution first
      -> obj.propName requires 'obj' identifier resolution first

    General Patterns

    References



    Collection With General Patterns

    JavaScript Patterns Book

    Function Patterns

    References



    Collection With Function Patterns

    JavaScript Patterns Book