JavaScript

Quick Recap

From class 1

Operators

Arithmetics

 

// + performs string or number addition

"hello" + 5 // hello5

// Rest of arithmetic operators perform number type casting

5 / '5' // 1
"hello" - 4 // NaN

// Unary + operator transforms value to number

+'-3' // -3

// The unary - operator transforms the value to number
// and performs a negation operation

-'3' // -3

[] + [] // ''    [].toString()
[] - [] // 0     Number([])

Operators

Arithmetics

 

// Unary ! negates the boolean representation of the value

!false // true
!"hello" // false

// Falsey values are 
NaN, undefined, 0, false, '', null

// ++ operator increments the value by one
var x = 5

var y = ++x // Increments and return the value
var z = y++ // Returns and increments the value

// -- operator decrements the value by one

Operators

Other

 

// typeof returns the type of the variable

typeof 2  // returns 'number'
typeof true // returns 'boolean'

// delete removes a property from an object

var a = { field: 'value' }

delete a.field // true

Operators

Comparission

// == performs a unestrict comparission

'5' == 5 // true

// === performs a strict comparission

'6' === 6 // false

Operators

spread operator

// can be used as an argument wherever 
// array arguments are expected

const a = [1, 2, 3]

const b = [5, ...a, -3 ]

// Also in functions

function doSomething(first, ...rest) {}

doSomething(...a)

Operators

spread operator

// can be used as any pair
// key-value arguments

const a = {
  property: 'one'
}

const b = {
 ...a,
 other: 'test'
}

Operators

spread operator

// can be destructured

const a = [1,2,3]
const [first, ...rest] = a


const c = {
  thing: 'test',
  address: {
    street: 'abc'
  }
}

const {address, ...obj} = c

Closures & Scope

var thing = 5

function makeSumator(a) {
  var x = 3;
  return function(b) {
    return b + x + a
  }
}

const sumatorThree = makeSumator(3)
const sumatorSeven = makeSumator(7)

sumatorThree(5) // 5 + 3 + 3
sumatorThree(6) // 6 + 3 + 3

The nature of types

2 built-in types

There are two built-in types in JS

Primitive types (boolean, number, string, null*, undefined*).

Reference types - Object, and the types that inherit from it. Fundamentals like Function and Error. Arrays. Regex. Date... Reference versions of primitives Number, Boolean, String.

The reference values are all objects

and primitive values are "autoboxed". Wrapped in a temporary reference object

var a = 'test'

'test'.contains('es')

var a = new Number(3)
var b = new Number(3)

a == b

3 == 3

Strings

'hello world'

`hello ${who}`

Strings can be created in different ways

"hello"
'hello'

typeof "hello" // string
typeof 'hello' // string

Template literals

 

var world = 'world'

var text = `hello

${world}`

Multiline strings the old way

var text = "this is a line \n" +
" this is another line"

The String global object is a constructor for strings, or a sequence of characters.

var a = new String('test')

typeof a // 'object'


var b = new String('test')

a == b // false because they are different objects

a == 'test' // true

a.valueOf() // 'test'
var c = {
  valueOf: function() {
     return 'test'
  }
}

c == 'test'

String methods

var a = 'test'

a.charAt(0) // 't'

a.indexOf('est') // 1

a.length // 4

a.toUpperCase() // 'TEST'

'TEST'.toLowerCase() // test

'TEST'.split('') // ['T', 'E', 'S', 'T']

Operators, numbers && strings

miniexam

The nature of functions

Functions are "subprograms" that can be called.
They have arguments, a name , a function body and return a value

function doSomething(arg, arg2) {
  console.log(arg, arg2)
}

Function expressions

var myFunction = function() { /* do something * /}

Function expressions can have a named or anonymous function

 

They are not hoisted

Can be used for recurssion

var factorial = function fac(n) {
    return n < 2 ? 1 : n * fac(n - 1); 
};

console.log(factorial(3));

Every function is a `Function` object
It inherints Function.prototype

function a() {}

// Function.prototype.length
a.length // 0

// Function.prototype.name
a.name // 'a'

// Function.prototype.apply()
// Function.prototype.call()
// Function.prototype.bind()

Understanding this

function f1() {
   return this
}

// In a browser:
f1() === window;

// In Node:
f1() === global;

the value of `this` is determined by how a function is called

strict mode

function f1() {
   'use strict';
   return this
}

f1() // undefined

window.f1() // window

in strict mode, unless calling the method from an object, the value of this remains undefined

ES2015

arrow functions retain the context of the enclosing scope

 

 Normal functions in JavaScript bind their own this value, however the this value used in arrow functions is actually fetched lexically from the scope it sits inside. It has no this, so when you use this you’re talking to the outer scope.

ES2015

function FooCtrl (FooService) {
  this.foo = 'Hello';
  FooService
  .doSomething((response) => this.foo = response);
}

ES2015

var obj = {
  bar: function() {
    var x = function() {
      return this
    };
    return x;
  }
};

var c = obj.bar()

c() // window

arrow functions retain the context of the enclosing scope

ES2015

var obj = {
  bar: function() {
    var x = (() => this);
    return x;
  }
};

var c = obj.bar()

c() // obj

arrow functions retain the context of the enclosing scope

in object methods

var obj = {
  name: 'pepe',
  getName: function() {
    return this.name
  }
};

when called in object methods, this points to the object

the New keyword

function Person(name) {
  this.name = name
}

const person = new Person('juan')

person.name // 'juan'

when using the "new" keyword, this gets bound to the new instance that is being created

changing this

function setName(name) {
  this.name = name
}

var person = {
  name: 'peter'
}


setName.call(person, 'parker')

the value of `this` is determined by how a function is called

It can be set during execution and can be different each time the function is called

Function.prototype.call()

function setName(name) {
  this.name = name
}

var person = {}

setName.call(person, 'pedro')

Function.prototype.apply()

function setData(name, surname) {
  this.name = name
  this.surname = surname
}

var person = {}

setData.apply(person, ['pedro', 'blanco'])

c for commas
a for array

Function.prototype.bind()

function setData(name, surname) {
  this.name = name
  this.surname = surname
}

var person = {}

const setPeter = setData.bind(person, 'peter')

setPeter('parker')
setPeter('not parker')

Creates a new function bound to a context and some arguments

Exercise

create a setter function that receives one argument and sets the value to this.

Test calling it from different objects
 

Exercise

repeat the previous exercise but use .call and .apply to send various arguments to the function

function arguments

`arguments` is a reserved keyword that stands for an "array like" object (but not array) that represents the call arguments of the function

Function.prototype.apply() arguments

function setNameAndSurname(name, surname) {
  this.name = name
  this.surname = surname
}

var person = {
  setData: function setData() {
    setNameAndSurname.apply(this, arguments)
  }
}

person.setData('hey', 'hello')

ES2015 (ES6) arguments

function setName(name, surname = 'pepe') {
  this.name = name
  this.surname = surname
}

Exercise

Create 2 functions that receives multiple arguments.
Call one function from the other using apply, and "arguments" reserved keyword

Exercise

With the previous functions. Bind the first to a fixed list of arguments

Imperative Vs Functional

Imperative

function simpleJoin(stringArray) {
 var accumulator = ‘’
 for (var i=0, l=stringArray.length; i < l; i++) {
   accumulator = accumulator + stringArray[i]
 }
 return accumulator
}

functional

function simpleJoin(stringArray, acc = '') {
  if(stringArray.length === 0) {
    return acc
  }

  const [first, ...rest] = stringArray

  return simpleJoin(rest, acc + first)
}

Array utilities

Array.prototype.map()

var newCars = cars.map(c => {
  return {
    ...c,
    clean: true
  }
})

Array.prototype.filter()

var newCars = cars.filter(c => c.clean === true)

Array.prototype.find()

var newCar = cars.find(c => c.name === 'Volvo FTurbo mix')

Array.prototype.reduce()

var carsWeight = cars
  .reduce((acc, next) => acc + next.weight, 0)

Some functional exercises

1 - Map over a list of numbers a return the square value

square([1,2,3])

// [ 1, 4, 9 ]

2 - Reduce the values of one array to get it's sum

sumAllElementsOfList([1,2,3])

// 6

3 - Do a  function that receives an array of arrays as arguments. Return the reduced value of the sum of each

sumList([1,2,3,4], [4, 54, 212, 213], [123,2312, 231])

// 3160

Modules

JavaScript Modules

Modules

Modules divide programs into clusters of code that, by some criterion, belong together and may share an interface.

More on Modules

Why modules?

JavaScript shares the global scope. Namespace pollution can happen a lot of code uses global variables

Why modules?

We can separate pieces of code that share a similar purpose o functionality.

 

This is more obvious in the case of libraries (or modules)

functions can be used to create the isolated module

var names = ["Sunday", "Monday",
            "Tuesday", "Wednesday",
             "Thursday", "Friday",
             "Saturday"];
function dayName(number) {
  return names[number];
}

dayName(0) // "Sunday"

functions are the only thing that will create a new scope, so functions are needed to create a module

var dayName = function() {
  var names = ["Sunday", "Monday", 
               "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return function(number) {
    return names[number];
  };
}();

dayName(0) // "Sunday"

Objects as interfaces

var weekDay = function() {
  var names = ["Sunday", "Monday", 
               "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];
  return {
    name: function(number) { return names[number]; },
    number: function(name) { return names.indexOf(name); }
  };
}();

Allows to expose certain methods or properties and leave the rest hidden from the outside world

Objects as interfaces

(function(exports) {
  var names = ["Sunday", "Monday", 
               "Tuesday", "Wednesday",
               "Thursday", "Friday", "Saturday"];

  exports.name = function(number) {
    return names[number];
  };

  exports.number = function(name) {
    return names.indexOf(name);
  };
})(this.weekDay = {});

For larger modules we can use another pattern

Modules internal state

var counterModule = (function() {
  let counter = 0;

  const increment = () => ++counter;
  const decrement = () => --counter;
  
  return {
    increment,
    decrement
  }
})()

Modules can have it's internal state and manage it without conflicting with the global state

Standard module patterns

CommonJS, AMD & ES6 Modules

AMD

Asynchronous Module Definition

define('myModule', 
    ['math', 'graph'], 
    function ( math, graph ) {
 

        return {
            plot: function(x, y){
                return graph.drawPie(math.randomGrid(x,y));
            }
        }
    };
});

Defined for the browser, with an asynchronous behaviour in mind

CommonJS

function doSomething() {
  // Do
}

function doAnother() {
  // Do
}

module.exports = {
  doSomething: doSomething,
  doAnother: doAnother
}

CommonJS

var myModule = require('./myModule')

myModule.doSomething();
myModule.doAnother();

Can this be used in the browser?

ES6

export const list = [1, 2, 3]

export const doSomething = (cb) => list.map(cb)

export function doAnother (cb) {
  return list.filter(cb)
}

export default function() {
  console.log('a')
}

With ES6 JavaScript for the first time has a built-in module system.
Each file is a module
 

ES6

import * as myModule from './mymodule'

import { doSomething, doAnother } from './mymodule'

import mything from './anothermodule'

Importing modules

https://github.com/rafinskipg/test-setup-webpack

Modules

Exercises

0 - Start a new project

$> mkdir usersManagementApplication
$> cd usersManagementApplication
$> npm init
// create main.js
// launch with node main.js

1 - Create a users module

Use CommonJS for native node JS support.
 

  1. The module holds the internal state of users.
  2. It exports a "find" method that helps you find a user by name
  3. It exports a "update" method that updates the value of the user in the internal state
  4. It exports a "get" method that returns the list of users

2 - Add ES6 support to your project

npm install --save-dev babel-{core,loader,preset-es2015-native-modules} webpack
https://github.com/rafinskipg/test-setup-webpack

3 -Push your code to your preferred version control system.

We are going to use it later

(Github, Gitlab, bitbucket, dropbox? zip? email to a friend? print in paper?)

Objects

what is an object?

An object is a "box" that provides an interface for abstracting logic and hiding complexity.

objects in JS 

They have methods.

var beers = {
  amount: 50,
  drinkBeer: function() { --this.amount },
  buyBeer: function() { ++this.amount }
}

Methods are properties that hold a function value

Sharing methods and unique context

function collide(wall) {
  console.log(`the person ${this.name}
    collided with the ${wall}`)
}

const personOne = {
  name : 'petorski',
  collide: collide
}

const personTwo = {
  name : 'markantu',
  collide: collide
}

personOne.collide('dirty ass')

personTwo.collide('green wall of doom')

Prototype

Almost all objects have a prototype that they use for inheriting methods and properties

var a = {}

a.toString

we call JavaScript a prototypal inheritance language

The prototypal inheritance forms a tree shaped structure.

Since everything "inherits" from Object.prototype

different branches

 

Functions derive from Function.prototype
Arrays from Array.prototype

Normal objects from Object.prototype

 

Object constructors

As we have seen we can create new instances of objects with function constructors

function Engine() {
  this.started = false
}

function Car(model) {
   this.model = model
   this.engine = new Engine()
}

var tesla = new Car('tesla')

constructors prototype

we can define the prototype of the object constructors

Car.prototype.startEngine = function() {
  this.engine.started = true
}

Car.prototype.stopEngine = function() {
  this.engine.started = false
}

var tesla = new Car('tesla')

constructors prototype

the prototype property will be the prototype of instances created through it but is not its own prototype.

Object.getPrototypeOf(tesla)

{startEngine: ƒ, stopEngine: ƒ, constructor: ƒ}

Object.getPrototypeOf(Car)
ƒ () { [native code] }

Constructors owns prototype is the Function one

constructors prototype

Changing a constructors prototype is going to change all the instances at the same time

// tesla

Car.prototype.color = 'red'

tesla.color // red

Prototypes are objects, they are shared by all the instances by reference.

Be carefull

Accessing objects methods and properties

As we said, the prototype forms a tree of "inheritance", and for knowing which properties has an object, JavaScript does this in this way:

1 - It checks the object methods
2 - It checks it's prototype methods
3 - It checks it's prototype's prototype methods
... repeat

For performance, avoid long prototype chains

We can "extend" the language

Mutating Object.prototype can give us some good tools

Object.prototype.jotica = function() {
  console.log('La virgen del pilar diceeeeee')
}

var a = {}

a.jotica()

Exercise

Mutate Array.prototype to:

Create a method that returns the first element of the array

 

Create a method that returns the last element of the array

mutating is slow

why?

Access to prototype is fast, and often objects are predictable. In that case the JIT compiler stores the instructions to reuse them.

JIT

mutating is slow

why?

But when we mutate a prototype, all the objects that used that prototype have to be checked again by the JIT compiler.

Also... all the code the object flows through has to be re-checked, because the optimization relies in the form of the prototypes

JIT

Super exercise

Clone

https://github.com/rafinskipg/test-object-prototype

JavaScript Avanzado - Dia 2

By rafinskipg

JavaScript Avanzado - Dia 2

Segunda clase del curso de javascript avanzado

  • 516