Training Advanced JS

by JuanMa Garrido

Advanced JS Training

Teacher: JuanMa Garrido

Contents

  1. TDD/BDD w/ Jasmine
  2. Advanced JS concepts: Functions & Closures
  3. Advanced JS concepts: Arrays & Functional Programming
  4. Advanced JS concepts: Objects & Inheritance
  5. jQuery
  6. jQuery
  7. Workflow Tools: NPM, Grunt, Bower & Yeoman
  8. ES2015 (ES6)
  9. ES2015 (ES6)
  10. Frontend Arquitecture w/ ES6 Modules: Bundles & Asynchronous loading (w/ Webpack, SystemJS, UMD)
Javascript Logo Jasmine Logo

Advanced JS Training

TDD/BDD with Jasmine

Contents

Contents

KATA: Native function myIndexOf()

Implement the JavaScript native function myIndexOf()

The myIndexOf() method returns the index within the calling String object of the first occurrence of the specified value, starting the search at fromIndex , returns -1 if the value is not found. The indexOf method is case sensitive.

Parameter Description
searchValue A string representing the value to search for.
fromIndex The location within the calling string to start the search from. It can be any integer between 0 and the length of the string. The default value is 0.

KATA: Native function myIndexOf()

KATA: Poker

Create a useful model of a standard 52-card deck of cards:

I should be able to draw a poker hand (5 card draw, not Texas hold 'em) and identify useful properties of the hand :

KATA: Poker

Resources for this Unit

Resources for this Unit

Katas

Javascript Logo

Advanced JS Training

Advanced Javascript concepts

Contents

var x = 'Hello World';
function foo(){
    var x;
    alert( x );
    x = 'New Value';
    alert( x );
}
foo();

¿Qué devolveran los alert? ¿Por qué?

function test() {
    foo();
    bar();
    var foo = function () {
        alert("this won't run!");
    }
    function bar() {
        alert("this will run!");
    }
}
test();

¿Qué devolverá la ejecución de test? ¿Por qué?

var a = 1;
function f() {
    var a = 2;
    function n() {
        alert(a);
    }
    n();
}
f();

¿Qué nos mostrará este código en el alert()? ¿Por qué?

Closures practice

Do the following exercises to practice closures http://nathansjslessons.appspot.com/lesson?id=1000

Contents

var mathy = function(x) {
    return function (y) {
        return function (z) {
            return (x / y) - z;
        }
    }
}

¿Cómo hariamos la operación (4 / 3) - 2 con este código en una linea?

var superGreeter = function(greeting) {
    return function(place) {
        return function(nickname) {
            return function(name) {
                return greeting + ', ' + name + '! Welcome to ' + place + ', ' + nickname + '.';
            }
        }
    } 
};
­
superGreeter('Hey')('Berlin')('old pal')('Hans')
//'Hey, Hans! Welcome to Berlin, old pal.'
­
hiParisBuddyGreeter = superGreeter('Hi')('Paris')('buddy');
helloTokyoGreeter = superGreeter('Hello')('Tokyo');
­
hiParisBuddyGreeter('Franz')
//'Hi, Franz! Welcome to Paris, buddy.'
helloTokyoGreeter('friend')
//[Function]
helloTokyoGreeter('friend')('Yuki')
//'Hello, Yuki! Welcome to Tokyo, friend.'

Functional programming workflow

Follow the steps on this repository to see the workflow of some functional programming code

Functional programming exercises

Do the exercises 1-27 to practice functional programming

Contents

function F() {
    function C() {
        return this;
    }
    return C();
}
var o = new F();

¿El valor de this se referirá al objeto global o al objeto o?

function C(){
    this.a = 1;
    return false;
}
console.log(typeof new C());

¿Cuál es el resultado de ejecutar este trozo de código?

var add = function (x, y) {
    this.val = x + y;
},
obj = { val: 0 };
add.apply(obj, [2, 8]);
console.log(obj.val);

¿Qué devolverá el console.log? ¿A quien apunta this al llamar add ?

var myObject = {
    func1:function() {
        console.log(this);
        varfunc2 = function() {
            console.log(this);
            varfunc3=function() {
                console.log(this);
            }();
        }();
    }
};
myObject.func1();

¿Qué devolverá la ejecución de myObject.func1? ¿Por qué?

var myObject = {
    myProperty:'Icanseethelight',
    myMethod:function() {
        var that=this;
        var helperFunction =  function() {
            console.log(that.myProperty);
            console.log(this);
        }();
    }
}
myObject.myMethod();

¿Qué devolverá la ejecución de myObject.myMethod? ¿Por qué?

KOAN Javascript-Jasmine

Do the following KOAN to practice javascript concepts

KOAN Javascript-Jasmine

jQuery Logo

Advanced JS Training

Using jQuery

Contents

Contents

jQuery Exercises

Do the following exercises and then let's share and comment the solutions

KOAN jQuery

Do the following KOAN to assure the understanding of jquery concepts

Resources for this Unit

npm logo grunt logo bower logo yeoman logo

Advanced JS Training

Workflow Tools

Before starting...

For this section you need to install at your machine the following:

  1. Node.js and NPM from https://nodejs.org/en/download/ (the installation of node.js includes NPM)
  2. Git from http://git-scm.com/downloads
  3. To use Grunt, Bower and Yeoman from comand line we have to install them globally → npm install -g yo bower grunt-cli

Contents

Using Grunt in an existing project

Using Grunt in an existing project

$ git --version
$ node -v
$ npm -v
$ npm install -g grunt-cli
$ git clone git@github.com:juanmaguitar/training-js-vueling.git
$ cd training-js-vueling
$ npm install
$ grunt --version
$ grunt -h
$ grunt tasks
$ grunt compass
$ grunt shower
$ grunt serve

Using Grunt in an existing project

[+]

Creating my first Grunt project

Creating my first Grunt project

.
├── Gruntfile.js
├── package.json
$ mkdir project
$ cd project/
$ mkdir src
$ npm init
$ npm install --save-dev grunt
$ vi Gruntfile.js
  module.exports = function(grunt) {
    grunt.registerTask('foo', function() {
           grunt.log.writeln('foo is running...');
    });
  };
$ grunt foo

Creating my first Grunt project

[+]

Clear Ideas about Grunt

Clear Ideas about Grunt

Clear Ideas about Grunt

{
  "name": "my-project-name",
  "version": "0.1.0",
  "devDependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-jshint": "~0.10.0",
    "grunt-contrib-nodeunit": "~0.4.1",
    "grunt-contrib-uglify": "~0.5.0"
  }
}

Clear Ideas about Grunt

module.exports = function(grunt) {
  grunt.initConfig({
    jshint: {
      files: ['Gruntfile.js', 'src/**/*.js', 'test/**/*.js'],
      options: {
        globals: {
          jQuery: true
        }
      }
    },
    watch: {
      files: ['<%= jshint.files %>'],
      tasks: ['jshint']
    }
  });
  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.registerTask('default', ['jshint']);
};

Loading Grunt plugins

Loading Grunt plugins

.
├── Gruntfile.js
├── package.json
└── src
    └── foo.js
$ mkdir project2
$ cd project2/
$ mkdir src
$ npm init
$ npm install --save-dev grunt grunt-contrib-jshint

Loading Grunt plugins

$ vi Gruntfile.js
  module.exports = function(grunt) {
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.initConfig({
      jshint: {
        options: {
          curly: true,
          eqeqeq: true
        },
        target1: ['Gruntfile.js', 'src/**/*.js']
      }
    });
    grunt.registerTask('default', ['jshint']);
  };
$ grunt

Loading Grunt plugins

[+]

Clear Ideas about Gruntfile.js

Clear Ideas about Gruntfile.js

Clear Ideas about Gruntfile.js

Contents

Fully functional Grunt project

├── Gruntfile.js
├── dist
├── index.html
├── package.json
├── src
│   ├── js
│   │   ├── bar.js
│   │   └── foo.js
│   ├── scss
│   │   └── styles.scss
│   └── vendor
│       └── jquery-2.1.3.js
└── test
  ├── barSpec.js
  └── fooSpec.js

Fully functional Grunt project

Fully functional Grunt project

Fully functional Grunt project (extras)

Fully functional Grunt project (extras)

Also, prepare the project w/ the following:

Resources for this Unit

es2015 logo

Advanced JS Training

ES2015

(former ES6)

ES2015 Overview

Arrow Functions

Arrow Functions

Arrow Functions

Four versions:

    (arg1, arg2, ...) => expr
    (arg1, arg2, ...) => { stmt1; stmt2; ... }
    singleArg => expr
    singleArg => { stmt1; stmt2; ... }

Arrow Functions

BEFORE (ES5)

var self = this;
this.element.addEventListener('click', function(event) {
  self.registerClick(event.target.id);
});

Arrow Functions

AFTER (ES2015)

this.element.addEventListener('click', event => {
  this.registerClick(event.target.id);
});

Arrow Functions

BEFORE (ES5)

[1,3,4,5,6,7].filter(function(n) { return n % 2 } )
  .map(function(n, i) { return n + i } ); 
// [1, 4, 7, 10]

Arrow Functions

AFTER (ES2015)

[1,2,3,4,5,6,7].filter(n => n % 2).map((n, i) => n+i);

ES6 Katas: Arrow Functions

Do the following katas to assure the understanding of arrow functions

Block Scope

Block Scope

Block Scope

BEFORE (ES5)

var arr = [1, 2, 3];
for (var i = 0; i < arr.length; i++) {
  // i from 0 to 2
}
i; // 3
{
  var TEMPERATURE = 32;
  TEMPERATURE = 16;
  TEMPERATURE // 16
}
TEMPERATURE; // 16

Block Scope

AFTER (ES2015)

var arr = [1, 2, 3];
for (let i = 0; i < arr.length; i++) {
  // i from 0 to 2
}
i; // ReferenceError: i is not defined!
{
  const TEMPERATURE = 32;
  TEMPERATURE = 16;
  TEMPERATURE; // 32
}
TEMPERATURE; // ReferenceError: TEMPERATURE is not defined!

ES6 Katas: Block Scope

Do the following katas to assure the understanding of Block Scope

Template Strings

`string text`
­
`string text line 1
 string text line 2`
­
`string text ${expression} string text`

Template Strings

BEFORE (ES5)

var name = "juanma";
var getSuitableDrink = function(who) {
  return who === 'juanma' ? 'beer' : 'cocktail'
};
­
console.log( 'Hello, '+name+'!\nFancy a '+getSuitableDrink()+'?' );
­
// Hello, juanma!
// Fancy a beer?

Template Strings

AFTER (ES2015)

var name = "juanma";
var getSuitableDrink = function(who) {
  return who === 'juanma' ? 'beer' : 'cocktail'
};
­
console.log( `Hello, ${ name }!
  Fancy a ${ getSuitableDrink() }?` );

Template Strings

ES6 Katas: Template Strings

Do the following katas to assure the understanding of template strings

Enhanced Object Literals

Enhanced Object Literals

var a = "foo",
    b = 42,
    c = {};
­
function myMethod() {
    console.log('ooOoh!');
}
­
// Shorthand property names
var o = { a, b, c };
­
// Shorthand method name and dynamic property name
var o2 = {
  myMethod,
  ['myPropertyNum'+b]: 'bar'
}

Enhanced Object Literals

var messages = {
  get latest () {
    if (this.log.length == 0) return undefined;
    return this.log[this.log.length - 1]
  },
  set current (str) {
    this.log[this.log.length] = str;
  },
  log: []
}
­
messages.current = "hey!";
messages.latest // hey!

ES6 Katas: Enhanced Object Literals

Do the following katas to assure the understanding of Enhanced Object Literals

Default parameters

function f(x, y=12) {
  // y is 12 if not passed (or passed as undefined)
  return x + y;
}
­
f(3) === 15;
f(3, undefined) === 15;

ES6 Katas: Default parameters

Do the following katas to assure the understanding of Default parameters

Destructuring Assignment

Destructuring Assignment

var [first, second, third, , fifth = 5] = [1, 2];
first // 1
second // 2
third // undefined
fifth // 5
­
[second, first] = [first, second] // swap values
first // 2
second // 1

Destructuring Assignment

var customer = {
  name: 'John',
  surname: 'Doe',
  dateOfBirth: {
    year: 1988
  }
};
­
var {name, surname, dateOfBirth: {year}, children} = customer;
name // 'John'
surname // 'Doe'
year // 1988
children // undefined

ES6 Katas: Destructuring Assignment

Do the following katas to assure the understanding of Destructuring Assignment

Rest operator

function multiply(multiplier, ...numbers) {
  return numbers.map(n => multiplier * n);
}
­
var arr = multiply(2, 1, 2, 3);
console.log(arr); // [2, 4, 6]

ES6 Katas: Rest operator

Do the following katas to assure the understanding of Rest operator

Spread operator

function f(x, y, z) {
  return x + y + z;
}
­
var arr = [1, 2, 3];
f(...arr) === 6; // true
­
[0, ...arr, 4, 5, 6, 7]; // [0, 1, 2, 3, 4, 5, 6, 7]

ES6 Katas: Spread operator

Do the following katas to assure the understanding of Spread operator

Set

var s = new Set();
s.add("hello").add("goodbye").add("hello");
s.size === 2;
s.has("hello") === true;
s.delete("hello");
s.has("hello") === false;

ES6 Katas: Set

Do the following katas to assure the understanding of Set

Map

Map

var m = new Map();
m.set("hello", 42);
m.get("hello") === 42;
­
var s = { n:4 };
m.set(s, 34);
m.get(s) === 34;

Map

var myMap = new Map();
­
var keyString = "a string",
    keyObj = {},
    keyFunc = function () {};
­
// setting the values
myMap.set(keyString, "value associated with 'a string'");
myMap.set(keyObj, "value associated with keyObj");
myMap.set(keyFunc, "value associated with keyFunc");
­
myMap.size; // 3
­
// getting the values
myMap.get(keyString);    // "value associated with 'a string'"
myMap.get(keyObj);       // "value associated with keyObj"
myMap.get(keyFunc);      // "value associated with keyFunc"
­
myMap.get("a string");   // "value associated with 'a string'"
                         // because keyString === 'a string'
myMap.get({});           // undefined, because keyObj !== {}
myMap.get(function() {}) // undefined, because keyFunc !== function () {}

ES6 Katas: Map

Do the following katas to assure the understanding of Map

Clases

Classes

BEFORE

var Shape = function( id, x, y ) {
  this.id = id;
  this.x = x;
  this.y = y;
};
Shape.prototype.toString = function( x, y ) {
  return "Shape(" + this.id + ")"
};
­
var Rectangle = function( id, x, y, width, height ) {
  Shape.call( this, id, x, y );
};
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
Rectangle.prototype.toString = function() {
  return "Rectangle > " + Shape.prototype.toString.call( this );
};

Classes

AFTER

class Shape {
  constructor (id, x, y) {
    this.id = id;
    this.x = x;
    this.y = y;
    // or Object.assign(this, {id, x, y});
  }
  toString () {
    return `Shape(${this.id})`
  }
}
­
class Rectangle extends Shape {
  constructor (id, x, y, width, height) {
    super(id, x, y)
  }
  toString () {
    return "Rectangle > " + super.toString()
  }
}

Classes

ES6 Katas: Classes

Do the following katas to assure the understanding of Classes

Modules

Modules

// -------- jquery.js --------
export default function jQuery() {
  /* code */
}
­
// -------- code.js --------
import $ from 'jquery';
$('body').addClass('yay');

Modules

// --------- http.js --------
export function get(url) {
  /* code */
}
­
export function post(url, body) {
  /* code */
}
­
// -------- code.js --------
import { get, post } from 'http';
import { TIMEOUT as HTTP_TIMEOUT } from 'http';
import * as http from 'http';
­
get('/my/url').then(function(result) {
  /* code */
});
­
HTTP_TIMEOUT; // 1000;
http.post('/my/url', 'body');

ES6 Katas: Modules

Do the following katas to assure the understanding of Modules

Array

Array object extended with:

Array

Array.from(arguments) // [].slice.call(arguments);
Array.from({0: 'hello', 1: world, length: 2}); // ['hello', 'world']
Array.of(1, 2, 3) // [1, 2, 3]
­
[1, 2, 3, 4, 5].copyWithin(0, 3, 4) // [4, 2, 3, 4, 5]
[1, 2, 3].fill(4) // [4, 4, 4]
[4, 5, 8, 12].find(isPrime) // 5
[4, 5, 8, 12].findIndex(isPrime) // 2
[4, 5, 8, 12].keys() // iterator from 0 to 3
[4, 5, 8, 12].values() // iterator from 4 to 12

ES6 Katas: Array

Do the following katas to assure the understanding of Array

String

String object extended with:

String

String.raw`Line 1\nLine 2\nLine 3` // 'Line 1\\nLine 2\\nLine 3'
'Hello world'.startsWith('Hello') // true
'Hello world'.endsWith('world') // true
'Hello world'.includes('orl') // true
'Hello world'.repeat(2) // 'Hello worldHello world'

Promise

Promise

var promise = new Promise(function(resolve, reject) {
  // Do something asynchronous and call resolve with the
  // result or reject with the error
});
­
promise.then(function(result) {
  // Use the result of the async call
}, function(error) {
  // Process the error
});

Promise

var allPromise = Promise.all([getLocation, getTemperature]);
allPromise.then(function(location, temperature) {
  console.log('The location is ', location,
        'and the temperature is', temperature);
}, function(error) {
  // Process the error
});
­
var racePromise = Promise.race([getGoogleAds, getYahooAds, getBindAds]);
racePromise.then(function(ads) {
  page.addAds(ads);
});

ES6 Katas: Promise

Do the following katas to assure the understanding of Promise

Resources for this Unit

es2015 logo babel logo webpack logo

Advanced JS Training

Frontend Architecture

ES2015, UMD modules & webpack

ES2015, UMD modules & webpack

$ git clone https://github.com/juanmaguitar/project-es2015-webpack-umd.git
$ cd project-es2015-webpack-umd
$ npm install
$ npm start 
$ node dist/project-babel-webpack.js
$ open "index.html"

ES2015, UMD modules & webpack

ES2015, SystemJS & Grunt

ES2015, SystemJS & Grunt

$ git clone https://github.com/juanmaguitar/project-es2015-systemJs.git
$ cd project-es2015-systemJs
$ npm install
$ grunt serve

ES2015, SystemJS & Grunt

ES2015 & webpack (browser)

ES2015 & webpack (browser)

$ git clone https://github.com/juanmaguitar/webpack-multiple-entry-points.git
$ cd webpack-multiple-entry-points
$ npm install
$ npm start

ES2015 & webpack (browser)

Resources

Resources

Final Resources