(better presented by @drpicox)
Slides of an introductory course for web programming focusing in basic Javascript and CSS concepts. It assumes knowledge of programming, Java or C#.
16. Number (immutable)
• IEEE-754: 1, 2, 5, 5000, -10, 3.14, 1e2, 1e-2, Infinity, NaN, …
• Methods: toFixed, toExponential, …
• Math: it has all methods and constants that Number should
have
• Cast to number:
• let number = Number(value);
• let number = parseInt(value, 10);
• let number = +value;
16
18. String (immutable)
• Any UCS-2 chain: 'hello', 'a', 'long word', …
• Character is length 1 string
• 'e' === 'hello'[1]
• Properties/Methods: length, slice, trim, concat, split, indexOf,
…
• Cast to string:
• let string = String(value);
• let string = value.toString();
• let string = '' + value;
18
19. String (immutable)
let single = 'single comma string';
let double = "double comma string";
let template = `template with ${'inter' + "polation"}`;
19
25. Array
• [1,2,3], [42,'sense',{of: 'life'}], [], …
• Properties: length, push/pop, shift/unshift, slice, map/reduce/
every/some, indexOf…
• Mixed content:
• Allow contents of different type for each element, including other
arrays
• Dynamic length:
• array = ['a','b','c']; array[4] = 'e';
• array[3] === undefined
• array.length = 3
25
26. Array mutators
26
// As stack
let array = ['b','c','d'];
array.push('e');
let e = array.pop();
array.unshift('a');
let a = array.shift();
// As queue
array.push('e');
let b = array.shift();
array.unshift('a');
let e = array.pop();
// Insert
let array = ['a','c','d'];
array.splice(1, 0, 'b');
// Remove
let array = ['a','x','b','c'];
array.splice(1, 1);
// Sort
let array = ['c','a','b'];
array.sort();
// Reverse
let array = ['c','b','a'];
array.reverse();
27. Array non-mutators
// As functional array
let copy = array.slice();
let numbers = ['a','b',1,2,3,'c'].slice(2,5);
let moreNumbers = [1,2,3].concat([4,5]);
let odds = numbers.filer(n => n % 2);
let doubles = numbers.map(n => n * 2);
let sum = numbers.reduce((s,n) => s + n);
let allPositives = numbers.every(n => n >= 0);
let thereIsATwo = numbers.some(n => n == 2);
let firstBig = numbers.find(n => n >= 3);
let bigIndex = numbers.findIndex(n => n >= 3);
let indexOfTwo = numbers.indexOf(2);
// Spread destructuring
let copy = [...numbers];
let concat = [...numbers, 4, 5, ...[6, 7, 8]];
let [one,...tail] = numbers;
27
30. Objects
• JSON constructor is the most common one
• let car = { color: 'blue' };
• Are string key/any value maps:
• Get property:
obj.propertyName
obj['propertyName']
• Set property:
obj.propertyName = newValue
obj['propertyName'] = newValue
30
31. Object
// Object is a Map:
// pairs string-value (properties)
let object1 = {
property: 'anyValue',
};
let object2 = new Object();
object.property = 'anyValue';
let object3 = new Object();
object['prop' + 'erty'] = 'anyValue';
31
32. Object
// By default, you can set any property
object.property = 'anyValue';
// And you can get any value
let value = object.property;
console.assert(value === 'anyValue');
// even if not defined
let notDefined = object.notDefined;
console.assert(notDefined === undefined);
32
33. Be Careful
let car = {
color: 'blue'
};
let carOwners = {};
carOwners[car] = 'elon';
JSON.stringify(carOwners); // hint: car is not string
33
34. Objects
// Spread & destructuring (in standardisation)
let main = {peter: 'tyrion', lena: 'cersei'};
let others = {sean: 'eddard', jason: 'khal'};
let copy = {...main};
let addFields = {...main, emilia: 'daenerys'};
let composed = {...main, ...others};
let {peter, lena} = main;
let {peter, ...rest} = main;
// Computed keys
let main = {['peter']: 'tyrion'};
// shorthand property names
let peter = 'tyrion';
let main = { peter };
34
36. Functions
• Are Objects
• Like arrays, numbers, strings, ...
• You can assign to a variable, object property, passed as an
argument, returned as result...
• Do not use new Function('n', 'n * 2')
36
37. Functions
// Short notation
const incr = a => a + 1;
const incr = (a) => a + 1;
const incr = a => { return a + 1; };
const incr = (a) => { return a + 1; };
const sum = (a, b) => a + b;
const sum = (a, b) => { return a + b };
37
38. Functions
// Short notation in object definition
const incrementer = {
incr(a) {
return a + 1;
},
};
incrementer.incr(3); // 4
// Long notation: function definition
function incr(a) {
return a + 1;
}
// Long notation: function expression
const incr = function(a) {
return a + 1;
}
38
39. Functions
// Function arguments can missmatch
incr(1) // === incr(1, ignoreOtherArguments)
incr() // === incr(undefined)
// Variable arguments
const sum = (first, ...rest) => first + sum(...rest);
sum(1, 2, 3) === sum(...[1, 2, 3])
// Arguments may have default values
const add = (a, b = 1) => a + b;
add(3) === 4
39
40. Functions
// May return any kind of object
const cast(tony, pepper) => ({ tony, pepper });
// No return or empty return is undefined
const makeUndefined() => { return; };
// Be careful: semicolon is optional (ops undefined)
const makeThree() => {
return
1 + 1 + 1;
};
40
41. Functions
// High order functions
const reduce = (array, fn, zero) => {
if (array.length === 0) { return zero; }
return fn(
array[0],
reduce(array.slice(1), fn, zero),
);
};
const add = (a, b) => a + b;
const sum = (array) => reduce(array, add, 0);
41
43. Class
• Are new in ES2015
• They can be transpiled to any browser that supports
Object.create and Object.defineProperties
• It uses a notation similar to object short hand
• There are no private fields (yet)
43
44. Class
// have one single constructor
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
// new instances with new
const square = new Rectangle(5, 5);
// access to set/get like any object
square.width = square.width + 1;
square['height'] = square['height'] + 1;
44
45. Class
// have functions (no methods)
class Animal {
speak() {
return 'makes noise';
}
}
// has not method overloading
class Animal {
speak() {
return 'makes noise';
}
speak(predatorNear) { // avoid duplicates
return predatorNear ? 'is silent' : 'makes noise';
}
}
45
46. Class
// may have "methods"
class Rectangle {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
// new instances with new
const square = new Rectangle(5, 5);
// access to set/get like any object
square.width = square.width + 1;
square['height'] = square['height'] + 1;
46
47. Class (this)
// use «this» to access private members
class Pet {
constructor(name) {
this.name;
}
getName() {
return this.name;
}
salute() {
return `Hi ${this.getName()}`;
}
speak() {
return 'makes noise';
}
}
47
48. Class (this)
// there is no method
const boby = new Pet('boby');
// only functions
const speak = boby.speak;
speak();
const getName = boby.getName;
getName();
const lucas = {
name: 'lucas',
getName
};
lucas.getName();
48
METHOD
giphy.com
49. Class
// use extends for inheritance
class Animal {
speak() {
return 'makes noise';
}
}
// add behaviour
class Cat extends Animal {
purr() { … }
}
// or redefine behaviour
class Lion extends Cat {
speak() { return 'roars'; }
}
49
51. Closures
• Functions inside functions can access to variables and
arguments of outer functions.
• Variables and arguments keep their existence after the outer
function is finished.
51
54. Closures
// The equivalent in old Java
public IntSupplier makeCounter(int initial) {
final AtomicInteger counter =
new AtomicInteger(initial);
return new IntSupplier() {
public int getAsInt() {
return counter.getAndIncrement();
}
};
}
54
55. Closures
55
Function Call 4
Return @address
Stack
Function Call 3
Return @address
Function Call 2
Return @address
Function Call 1
Return @address
Current
Stack Frame
Grow
Local Variables
Local Variables
Local Variables
Local Variables
56. Closures
56
Function Call 4
Return @address
Stack
Function Call 3
Return @address
Function Call 2
Return @address
Function Call 1
Return @address
Local Variables
Local Variables
Local Variables
Local Variables
Scopes
Global
Scope
Parent Scope
new
new
new
new
57. Closures
// Use as callbacks
const startClock = () => {
let count = 0;
let intervalId = setInterval(() => {
console.log(count += 1);
}, 1000);
return () => {
clearInterval(intervalId);
};
};
let stopClock = startClock();
// …wait few seconds…
stopClock();
57
58. Closures
// Use to create modules
let myObj = (() => {
let privateState = …;
const privateFunction = () => { … }
return {
publicMethodA: function() {
…do something with privateState…
},
publicMethodB: function() {
…do something with privateFunction…
},
…
};
}());
58
60. Async/Await
• Javascript is asynchronous in its foundation.
• Traditionally it uses callbacks to handle asynchronicity: you
pass a function which is called when the operation is finished
with the resulting data as argument.
• ES2015 standarises: a kind of object for dependency inversion,
it allows you to call an operation before knowing which function
(or functions) handles the resulting data.
• ES2017 introduces async/await: promises were introduced in
the core, and functions can natively generate them and
consume them emulating a synchronized methods (but they
are not blocking and may be interleaved with other callbacks)
60
61. Async/Await
• There is only one thread
• no interferences
• no semaphores
• no deadlocks
• no quantum loss
• but also:
• no parallel processing
• no preemption (a callback may freeze the whole system)
61
80. Import/Export
• Allows to link with other files and get and publish symbols
• Symbols can be named or default
• Two path import possibilities:
• paths beginning with package-name import from package
• relative paths (a.k.a. './…') import from file in the current directory
• It has fallbacks:
• it automatically appends .js .jsx or .json if not specified
• if destination is a folder it reads index.js[x]
80
81. Import/Export
import rule from "./rule";
import * as math from "math-tools";
import { sqrt } from "math-tools";
import { sqrt as sq } from "math-tools";
import { min, max } from "math-tools";
import { min, max as big, … } from "math-tools";
import defaultMember, { sqrt } from "math-tools";
import defaultMember, * as math from "math-tools";
import "math-tools";
81
82. Import/Export
export { sqrt, min, max };
export { squareRoot as sqrt, min, max };
export let sqrt, min, max;
export let min = (a,b) => a < b ? a : b;
export const min = (a,b) => a < b ? a : b;
export default expression;
export default function (…) { … }
export default async function (…) { … }
export default async class (…) { … }
export default function sqrt(…) { … }
export { sqrt as default, … };
export * from './other-file';
export { name1, name2, …, nameN } from './other-file';
export { import1 as name1, name2, …, nameN } from …;
82
85. Object
• Java, C#, C++, … are class oriented
• Classes inherits from other Classes
• Javascript is instance oriented
• Objects (instances) inherits from other objects
85
car:
prototype is
mcQueen: raceCar:
prototype is
Car
instance of
mcQueen: RaceCar
inherits from
86. Object
• Javascript is “classless” but has inheritance
• Java, C# is class oriented
• Javascript is instance oriented
• Inheritance is performed through prototype
• Every object can become a prototype of other object
• Every object has another object as prototype
• The main prototype of almost all objects is Object.prototype
86
87. Object
// By default objects have a Object's prototype
let car1 = {
color: 'blue',
};
let car2 = Object.create(Object.prototype);
car.color = 'blue';
87
carX:
.color
Object.prototype:prototype is
89. Object
// But it can have no prototype
let prototypelessObject = Object.create(null);
// Object.getPrototypeOf(prototypelessObject) ?
// Object.getPrototypeOf(Object.prototype) ?
// Object.getPrototypeOf(Object) ?
89
prototypelessObject: nullprototype is
90. Object
// Objects can have any object as prototype
let car = {
color: 'blue',
};
let tesla = Object.create(car);
// car.color ?
// tesla.color ?
90
car:
.color
Object.prototype:tesla:
prototype is
has value fallback
prototype is
has value fallback
91. Object
// Objects inherits its prototype properties
let car = {
color: 'blue',
};
let tesla = Object.create(car);
tesla.brand = 'tesla';
// tesla.color ?
// tesla.brand ?
// Object.keys(tesla) ?
91
car:
.color
tesla:
.brand
92. Object
// Objects can overwrite prototype properties
let car = {
color: 'blue',
};
let ferrari = Object.create(car);
ferrari.color = 'red';
// car.color ?
// ferrari.color ?
92
car:
.color
ferrari:
.color
93. Be Careful
let car = {
color: 'red'
};
let parkingSpot = {
car: car,
};
let wolowitzParkingSpot = Object.create(parkingSpot);
wolowitzParkingSpot.car.color = 'gray';
// wolowitzParkingSpot.car.color ?
// car.color ?
93
car:
.color
parkingSpot:
.car
94. Object
class Object {
private Map<String,Object> properties;
private Object prototype;
public Object get(String key) {
if (properties.containsKey(key)) {
return properties.get(key);
} else if (prototype != null) {
return prototype.get(key);
} else {
return Undefined;
}
}
public void set(String key, Object value) {
properties.put(key, value);
}
}
94
95. Object
• In matter of speaking:
• Object.method.property are like Java/C# static members
ex: Object.create
• Object.prototype.property are like Java/C# instance members
ex: Object.prototype.isPrototypeOf
• Only properties, in matter of speaking:
• methods are properties whose value is a function
• members are properties whose value is not a function
• Object is a map, with an optional fallback map called prototype
95
96. Be Careful
let wordCount = {};
let word;
while (word = getSomeWord()) {
if (wordCount[word]) {
wordCount[word] ++;
} else {
wordCount[word] = 1;
}
}
// does it works? always?
96
106. Class
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + ' makes a noise');
};
let fievel = new Animal('fievel');
106
Animal.prototype:
.speak
fievel:
.name
107. Class
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + ' makes a noise');
};
let fievel = new Animal('fievel');
let tanya = new Animal('tanya');
107
Animal.prototype:
.speak
tanya:
.name
fievel:
.name
108. Class
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + ' makes a noise');
};
let fievel1 = new Animal('fievel');
let fievel2 = Object.create(Animal.prototype);
Animal.call(fievel2, 'fievel');
108
109. Class
function Animal(name) { this.name = name; }
Animal.prototype.speak = function() { … };
function Lion(name) {
Animal.call(this, name + ' the lion');
}
Lion.prototype = Object.create(Animal.prototype);
Lion.prototype.constructor = Lion;
Lion.prototype.speak = function() {
console.log(this.name + ' roars!');
};
109
Animal.prototype:
.speak
.constructor
Lion.prototype:
.speak
.constructor
110. Class
class Animal {
constructor(name) {
this.name = name;
}
speak() {
console.log(this.name + ' makes a noise');
}
}
class Lion extends Animal {
constructor(name) {
super(name + ' the lion');
}
speak() {
console.log(this.name + ' roars');
}
}
110
111. Class
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(this.name + ' makes a noise');
}
class Lion extends Animal {
constructor(name) {
super(name + ' the lion');
}
speak() {
console.log(this.name + ' roars');
}
}
111