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
- 583