JavaScript for
non-JavaScripters

Marian Rusnak

Oath

18th October 2017

Agenda

  • Functions
  • Variable scope
  • Callbacks
  • Classes/objects/inheritance
  • Value of 'this'
  • Promises etc.
var number = 10;
var string = 'Hello';
var bool = true;

var object1 = new Object(); // Don't use.
var object2 = {};

var array1 = new Array(); // Don't use.
var array2 = [];

var date = new Date();
var regex = new Regex();

var func = function() {};

Types

Functions

function add(x, y) {
  var total = x + y;
  return total;
}

add(5, 10); // 15

Function Declarations

Function Expressions

// Anonymous function.
var add = function(x, y) {
  var total = x + y;
  return total;
};

add(5, 10); // 15
// Named function.
var add = function add(x, y) {
  var total = x + y;
  return total;
};

add(5, 10); // 15







foo();
bar(); // undefined

function foo() {
  console.log('Foo');
} // no semicolon

var bar = function() {
  console.log('Bar');
}; // semicolon

bar();

And what's the difference???

Hoisiting

var bar; // hoisted

// hoisted
function foo() {
  console.log('Foo');
} // no semicolon

foo();
bar(); // undefined





var bar = function() {
  console.log('Bar');
}; // semicolon

bar();

Arrow functions (ES6)

var add = (x, y) => {
  var total = x + y;
  return total;
};

add(5, 10); // 15
var add = (x, y) => x + y;

add(5, 10); // 15

Or simply...

IIFE

// Declared function.
function add(x, y) {
  var total = x + y;
  return total;
}


// Immediately invoked anonymous function.
(function() {
  var five = add(2, 3);
  var ten = add(5, 5);
})();

Immediately Invoked Function Expression

Variable

Scope

Function scope

// global
var a = 1;
var b = 2;


(function() {

  var b = 3; // local, doesn't change global
  
  a += b; // changes global

})();


a; // 4
b; // 2
if (condition) {
  console.log(value); // undefined
  var value = "blue";
}

value; // "blue"

Block scope (ES6)

function getValue(condition) {

  if (condition) {
    const value = "blue";

    return value;
  } else {
    // value doesn't exist here

    return null;
  }

  // value doesn't exist here
}

let, const

if (condition) {
  console.log(value); // ReferenceError
  const value = "blue";
}

Callbacks

Event Handlers

document.querySelector('#foo').addEventListener('click', function(e) {
  console.log('Clicked!');
});
var clickHandler = function(e) {
  console.log('Clicked!');
};

document.querySelector('#foo').addEventListener('click', clickHandler);

===

Closures

// global
var a = 1;
var b = 2;


document.querySelector('#foo').addEventListener('click', function(e) {
  a += b; // has access to outer scope

  a; // 3
  b; // 2
});

Classes
Objects
Inheritance

Object

var person = {
  
  name: 'Yeti',
  
  greet: function() {
    return 'Hello ' + this.name;
  }

};


person.greet(); // Hello Yeti

So simple

Object

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

Person.prototype.greet = function() {
  return 'Hello ' + this.name;
};


var person = new Person('Yeti');

person.greet(); // Hello Yeti

With a constructor

Classes (ES6)

class Shape {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
    
  logInfo() {
    console.log('X: ' + this.x + ', Y: ' + this.y);
  }
}

class Circle extends Shape {
  constructor(x, y, radius) {
    super(x, y); // parent constructor
    this.radius = radius;
  }

  // override method
  logInfo() {
    console.log('X: ' + this.x + ', Y: ' + this.y + ', Radius: ' + this.radius);
  }
}


var circle = new Circle(10, 20, 5);

This

...or that?

Event handlers

var obj = {
  val: 5,

  init: function() {
    document.querySelector('#foo').addEventListener('click', function() {
      console.log(this.val); // undefined
    });
  }
};

Context of 'this'

var obj = {
  val: 5,

  superMethod: function () {
    return this.val;
  }
};

console.log(obj.superMethod()); // 5


function logMethod(method) {
  this.val = 10;
  // obj.superMethod() invoked, this points to logMethod object
  console.log(method()); 
}


// obj.superMethod passed
logMethod(obj.superMethod); // 10

Value of 'this' set explicitly

var obj = {
  val: 5,

  superMethod: function () {
    return this.val;
  }
};

var obj2 = {
  val: 15
};

console.log(obj.superMethod()); // 5


function logMethod(method) {
  this.val = 10;
  // obj.superMethod() invoked, this points to obj2 object
  console.log(method.call(obj2)); 
}


// obj.superMethod passed
logMethod(obj.superMethod); // 15

call(), apply()

U can't touch 'this'

document.querySelector('#foo').addEventListener('click', function() {
  console.log(this.val); // 5
}.bind(this));
document.querySelector('#foo').addEventListener('click', () => {
  console.log(this.val); // 5
});

bind()

Arrow functions (ES6)

Promises

Promises vs callbacks

function isUserTooYoung(id, callback) {
  openDatabase(function(db) {
    getCollection(db, 'users', function(collection) {
      find(collection, {'id': id}, function(result) {
        result.filter(function(user) {
          callback(user.age < cutoffAge)
        })
      })
    })
  });
}
function isUserTooYoung(id) {
  return openDatabase()
    .then(getCollection)
    .then(find.bind(null, {'id': id}))
    .then(function(user) {
      return user.age < cutoffAge;
    });
}

Promise

// Fetch image asynchronously.
// Gives us a promise that the image will be fetched at some point.
var promise = fetchImage('image1.png');


// Image still not fetched at this point, but execution not blocked.
promise.then(function(url) {
  // Called when promise is successful = resolved.
  console.log(url + ' downloaded!');
});

promise.catch(function(reason) {
  // Called when promise has failed = rejected.
  console.log('Failed to download, reason: ' + reason);
});


// Image still not fetched at this point, but execution not blocked.

Promise

var promise = fetchImage('image1.png');

promise.then(function(url) {
  console.log(url + ' downloaded!');
});

promise.catch(function(reason) {
  console.log('Failed to download, reason: ' + reason);
});
fetchImage('image1.png')
  .then(function(url) {
    console.log(url + ' downloaded!');
  })
  .catch(function(reason) {
    console.log('Failed to download, reason: ' + reason);
  });

Simply

Promise

function fetchImage(url) {
  return new Promise(function(resolve, reject) {
    var img = new Image();
    img.onload = function(){
      // Call resolve when when successful.
      resolve(url);
    }
    img.onerror = function(){
      // Call resolve when on failure.
      reject(url);
    }
    img.src = url;
  });
}
fetchImage('image1.png')
  .then(function(url) {
    console.log(url + ' downloaded!');
  })
  .catch(function(reason) {
    console.log('Failed to download, reason: ' + reason);
  });

async/await

function logFetch(url) {
  return fetch(url)
    .then(response => response.text())
    .then(text => {
      console.log(text);
    }).catch(err => {
      console.error('fetch failed', err);
    });
}
async function logFetch(url) {
  try {
    const response = await fetch(url);
    console.log(await response.text());
  }
  catch (err) {
    console.log('fetch failed', err);
  }
}

Support

caniuse.com

node.green

Summary

  • Functions
    • Declarations, expressions, IIFE, arrow
  • Variable scope
    • Function, block
  • Callbacks, closures
  • Classes/objects/inheritance
    • Prototype inheritance
  • Value of 'this'
    • call(), apply(), bind()
  • Promises
    • async/await

References

  • MDN https://developer.mozilla.org
  • https://slides.com/marianr/es6-webelement
  • https://www.quora.com/Whats-the-difference-between-a-promise-and-a-callback-in-Javascript
  • https://developers.google.com/web/fundamentals/primers/promises

JavaScript for non-JavaScripters - Oath

By Marian Rusnak

JavaScript for non-JavaScripters - Oath

  • 509