Disclaimer: This presentation is mostly based on this post

About me

var presentationAuthor = {
  name: 'Augusto Altman Quaranta',
  betterKnownAs: 'tito',
  isA: 'Computer engineer', //and most of the time a human being :P
  livesIn: 'Cordoba, Argentina',
  worksAt: {
      corp: 'Intel Corporation',
      site: 'ASDC'
};

The two pillars of JavaSript

Chapter 1

Hello darkness, my old friend. I've come to code you again.

♫ Simon & Garfunkel - The sound of silence

That kind of stuff is usually sung by JavaScripters around the world

But don't misunderstand.

The problem isn't JavaScript. The problem is the way people learn it.

Actually, JavaScript rocks!

Because it's versatile

  • Functional.
  • Object oriented.
  • Event-based.
  • Procedural.

Because it's dynamic

  • Weakly typed.
  • No classes.
  • Native late binding.
  • Not compiled.
  • Eval.

Because it's open source

  • Based on ECMAScript.
  • All the best engines, tools and libraries are open source.
  • Most used language on GitHub.
  • You can always check the source code.

Because it's ubiquitous and universal

  • Standar language for web aplications.
  • All software is becoming web software.
  • Node.JS and io.js are taking over the server side.
  • Npm is the largest programming language package repository.
  • Available also for embeded systems.

You should be learning JavaScript right now.

The reallity

Almost everybody knows a little JavaScript, but almost nobody really understands JavaScript.

99 out of 100 JavaScript developers I interview lack the skills required to hit the ground running on a scalable production JavaScript application.

Eric Elliot.

The fact is, most of the world’s software infrastructure is heavily dependent on JavaScript: perhaps the world’s most misunderstood programming language.

Eric Elliot.

Chapter 2

Closures, closures everywhere.

First pillar.

Understanding closures is vital!

They enable state encapsulation and therefore are part of the language foundations.

There are two key concepts around closures:

  • First-class functions.
  • Function lexical scope.

First-class functions.

A first-class function is one that may participate as a normal data

i.e. be created literally at runtime, be passed as an argument, or be returned as a value from another function.

function someFun() {
  console.log('lalala');
}

function someOtherFunc(callback) {
  callback();
}

someOtherfunc(someFunc);

Lexical scopes.

For the sake conceptual clearity.

Context vs Scope

Every function invocation has both a scope and a context associated with it.

  • Scope pertains to the variable access of the function when it is invoked.
  • Context is always the value of the this keyword.

In programming languages scopes can be nested at any block level.

Types of nested scopes.

  • Lexical scopes, e.g: C++ (if/for/while), JavaScript (functions)
  • Dynamic scopes, e.g: Ruby (functions)

JavaScript allows scope nesting at function level.

Functions are lexical scoped in JavaScript.

JavaScript implements lexical scopes via the scope chain.

A function has access to the variables present in their outer enclosing functions.

Closures

Whenever a function is treated as data it must mantain its scope chain.

i.e. when we pass a function reference as an argument we are also passing its scope chain so it can be executed later maintaining its lexical scope.

And that's what a closure is!

Formally speaking: A closure is a pair consisting of the function code and the environment in which the function is created (its lexical scopes).

function funcFactory() {
  var name = "tito";
  function showName() {
    console.log(name);
  }
  return showName;
}

var aFunc = funcFactory();
aFunc();

Closures are a mechanism for containing encapsulated state.

So it's a means for encapsulation.

A great example of how closures provides encapsulation is the factory constructor function pattern.

From javascript.info patterns repository.

function Person(newPersonName, newPersonDeathAge) { //factory constructor function
  var name = newPersonName || 'tito';
  var deathAge = newPersonDeathAge || 80;
  var age = 0;
  return {
    reName: function (newName){
      name = newName;
    },
    getName: function (){
      return name;
    },
    happyBithday: function () {
      if(this.isAlive())
        age++;
    },
    getAge: function () {
      return age;
    },
    isAlive: function () {
      return this.getAge() < deathAge;
    }
  };
}
var josePerez = Person('jose', 30);
var juanRodriguez = Person('juan');

for(var i = 0; i<20; i++){
  josePerez.happyBithday();
}
juanRodriguez.happyBithday();
juanRodriguez.happyBithday();

console.log(josePerez.getAge()); //20
console.log(juanRodriguez.getAge()); //2

Encapsulation through closures can also be exploited to:

  • Propagate state through async calls.
  • Create namespaces.

Async state propagation.

Callbacks.

function TimeTalker(newMaxTime, newPhrase) {
  var maxTime = newMaxTime || 30;
  var phrase = newPhrase || 'soyez le tito';
  var interval;
  var counter = 0;
  return {
    start: function () {
      interval = setInterval(function callback(){
        console.log(phrase);
        counter++;
        if(counter >= maxTime) {
          clearInterval(interval);
        }
      }, 1000);
    }
  };
}

var aTalker = TimeTalker(5, 'closures are awesome');
aTalker.start();

Namespace creation.

Avoiding name crashes.

A great example of how closures provides namespacing is the module pattern.

Popularized by Douglas Crockford

var someVar = 'San Lorenzo de Almagro';
console.log(someVar); //San Lorenzo de Almagro

var Module = (function () { //IIFE
  var someVar = 'walla walla';
  var someOtherVar;
  console.log(someVar); //walla walla
  return function() {
    //doSomething
  };
})();

console.log(someVar); //San Lorenzo de Almagro

Chapter 3

Prototypal inheritance.

Second pillar.

Understanding prototypal inheritance is vital!

They enable code re-utilization and therefore are part of the language foundations.

In prototypal inheritance, instances inherit from other instances.

There are three kinds of Prototypal inheritance.

  • Delegative inheritance.
  • Concatenative inheritance.
  • Functional inheritance. (Identified by Douglas Crockford).

And the three of them are supported by JavaScript.

Delegative inheritance.

A delegate prototype is an object that serves as a base for another object.

The language is resposible of dispatching the correct method or finding the right piece of data simply by following a series of delegation pointers (from object to its prototype) until a match is found.

JavaScript provides natively delegation inheritance through the prototype chain mechanism.

There are two well-known ways for stablishing delegate prototypes:

  • Through the constructor pattern.
  • Through Object.create().

The constructor pattern

function Greeter(name) {
  this.name = name || 'John Doe';
}

Greeter.prototype.hello = function hello() {
  return 'Hello, my name is ' + this.name;
};

var george = new Greeter('George');

Object.create()

var proto = {
  hello: function hello() {
    return 'Hello, my name is ' + this.name;
  }
};

var george = Object.create(proto);
george.name = 'George';

Why delegation matters?

  • Method delegation is a fantastic way to preserve memory resources.
  • It’s a great way to add capabilities at runtime to all objects which share a particular prototype.

Concatenative inheritance.

Prototype cloning.

Prototype cloning is the process of copying the properties from one object to another, without retaining a reference between the two objects.

JavaScript allows dynamic object extension.

So any object strcutre can be changed at runtime by adding or removing properties.

var proto = {
  hello: function hello() {
    return 'Hello, my name is ' + this.name;
  }
};

//We are using the extend fuction from underscore.
var george = _.extend({}, proto, {name: 'George'});

Why concatenation matters?

  • Property access is faster because inherited properties are copied.
  • Objects may copy properties from any number of prototypes (composition).
  • It enables behavior extension patterns like mixins.

Functional inheritance.

Closure prototypes. Popularized by Douglas Crockford

Closure prototypes are functions that can be run against a target object in order to extend it.

They can hold encapsulated state and extend the new objects in order to they can hold it too.

var PersonModel = function (personAge, personOccupation) {
  var age = personAge || 0;
  var occupation = personOccupation || 'none';
  
  this.getOccupation = function () {
    return occupation;
  };
  
  this.getAge = function () {
    return age;
  };
  
  this.happyBirthday = function () {
    age++;
  };
};

var george = {
  name: 'George'
};

PersonModel.call(george, 13, 'student');

console.log(george.name); //George
console.log(george.getAge()); //13

Why closure prototypes matters?

  • It enables objects to be extended with encapsulated state.

Final thoughts

Some advices.

  • Favor composition over inheritance.
  • Favor the usage of factory constructor functions.
  • Read and learn JavaScript patterns for object creation and inheritance.
  • Read and learn about good and bad practices in JavaScript.
  • Use libraries that reduce the complexity of combining patterns and techniques (like stampit).

Takeaways.

  • Stop thinking JavaScript with the classical mindset.
  • The mechanism for providing code re-utilization and state encapsulation are always at a foundation level of any language.