Modern JavaScript

πŸ‘¨β€πŸ« Nicolas Payot

@nicolaspayot

Lead Front-End Developer [ Dawex ]

@npayot

nicolas.payot@gmail.com

OUTLINE

OUTLINE

1. Introduction to JavaScript

A bit of history...

1995 / 10 days / Brendan Eich

Ecma International

From Nov 1996 to Jun 1997

ECMAScript v1

ECMAScript

1

June 1997

Core syntax

ECMAScript

2

June 1998

Minor changes

ECMAScript

3

December 1999

Regular exp, try / catch, formatting for numeric output, ...

ECMAScript

4

Abandoned

Political differences about language complexity

ECMAScript

5

December 2009

"strict mode", JSON, Array prototype methods, getter / setter, ...

ECMAScript

6

June 2015

Classes, modules, for ... of, template literals, ...

ECMAScript

7

June 2016

Exponentiation operator (**), Array.prototype.includes

ECMAScript

8

June 2017

async / await, String padding, Object.values / .entries, ...

2. Primitive data types

boolean

A logical entity that can have 2 values: true and false

const foo = true;  // typeof foo => "boolean"

const bar = false; // typeof bar => "boolean"

null

An entity that exists but has no type or value

let foo; // typeof foo => "undefined"

const bar = null; // typeof bar => "object" (legacy reasons)

undefined

A variable that's not been assigned a value (⚠️ also a property of the global object)

let foo; // typeof foo => "undefined"

bar; // (window.bar) typeof bar => "undefined"

const baz = {};
baz.buzz; // undefined

number

An entity that's either an integer, floating point, or hexadecimal (integer)

const one = 1; // typeof one => "number"

const total = 10.1234; // typeof total => "number"

const hex = 0xFF; // (255) typeof hex => "number"

Number

number primitive wrapper

Number('1'); // 1

Number(false); // 0
Number(true); // 1

Number('hello'); // NaN

typeof NaN; // ?

Use to convert any value to a number

Number('1'); // 1

Number(false); // 0
Number(true); // 1

Number('hello'); // NaN

typeof NaN; // "number"

string

string literals or template literals (ES2015)

const hello = 'Hello, World!';

const name = 'John';

const helloJ1 = 'Hello, ' + name + '!';

const helloJ2 = `Hello, ${name}!`; // template literal

// helloJ1, helloJ2 => "Hello, John!"

3. Operators

Assignment operators

x = y

Assignment operators

x += y

πŸ‘‡

x = x + y

Assignment operators

x -= y

πŸ‘‡

x = x - y

Assignment operators

x *= y

πŸ‘‡

x = x * y

Assignment operators

x /= y

πŸ‘‡

x = x / y

Comparison operators

==

Returns true if operands are equal

Comparison operators

!=

Returns true if operands are not equal

Comparison operators

===

Returns true if operands are equal

AND of the same type

Comparison operators

!==

Returns true if operands are not equal

OR have different type

Comparison operators

>

Returns true if left operand is greater

than right operand

Comparison operators

>=

Returns true if left operand is greater than

or equal to right operand

Comparison operators

<

Returns true if left operand is less than right operand

Comparison operators

<=

Returns true if left operand is less than

or equal to right operand

Logical operators

&&

Returns true if left operand AND right operand is true

Logical operators

||

Returns true if left operand OR right operand is true

Logical operators

!

Returns false if its single operand can be converted

to true, otherwise true

Conditional (ternary) operator

condition ? val1 : val2 

Returns val1 if condition is true

and val2 ifΒ condition is false

4. Variables

var / let / const

Variables are named values and can be of any type

var hello = 'Hello, World!';
var FORTY2 = 42;
var _done = true;
var $$$ = 'money money';

Can start with letter, _ or $

var 2fast2furious = 'Vin Diesel';
var if = 'Nope, not working!';
var discount% = '10%';

πŸ‘Œ

πŸ‘Ž

var

GlobalΒ scope

var name = 'John Doe';
window.name // "John Doe"

⚠️ DO NOT DO THAT ⚠️

var

LocalΒ scope

function greetings() {
  var fullName = 'John Doe'; // Local scope
  return `Hello, ${fullName}`;
}
greetings();

fullName // Error: fullName is not defined
window.fullName // undefined

let (ES2015)

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // Global scope
  let b = 22; // Block scope (if)
}

a // ?
b // ?

BlockΒ scope

var a = 1;
var b = 2;

if (a === 1) {
  var a = 11; // Global scope
  let b = 22; // Block scope (if)
}

a // 11
b // 2

const (ES2015)

const foo; // Error: missing initializer

const bar = 'bar';
bar = 'buzz'; // Error: Assignment to constant

const creates a read-only reference to a value

const (ES2015)

const names = [ 'Alice', 'Bob' ];
names.push('John');

names // [ "Alice", "Bob", "John" ]

BUT the variable is not immutable

5. Functions

Function declaration

A function declaration has a name, (optional) params and a body

function sayHi() {
  console.log('Hi!');
}

sayHi(); // "Hi!", returns undefined

By default, a function returns undefined

Function declaration

With a return statement

function add(a, b) {
  return a + b;
}

add(1, 2); // 3

Function declaration

Hoisting ☝️

add(1, 2); // 3

function add(a, b) {
  return a + b;
}

The function can be used before it was declared

Function expression

A function expression has a (optional) name, (optional) params and a body

const sayHi = function() { // Anonymous function
  console.log('Hi!');
}

sayHi(); // "Hi!"

Function expression

With a name and params

const add = function addNumbers(a, b) {
  return a + b;
}

add(1, 2); // 3
add.name; // "addNumbers"

A function expression has a name property

Function expression

Arrow function (ES2015)

const add = (a, b) => {
  const sum = a + b;
  return sum;
}

add(1, 2); // 3

Function expression

Arrow function (ES2015)

const increment = a => {
  const b = a++;
  return b;
}

increment(1); // 2

Arguments parentheses are optional when there's only 1

Function expression

Arrow function (ES2015)

const add = (a, b) => a + b;

add(1, 2); // 3

Shorter functions: when there's only a return statement

Function expression

Hoisting ☝️

add(1, 2); // TypeError: add is not a function

var add = (a, b) => a + b;

⚠️ The function can NOT be used before

it was declared

Constructor function

function User(firstName, lastName) {
  this.firstName = firstName;
  this.lastName = lastName;
}

const john = new User('John', 'Doe');

john.firstName; // "John"
john.lastName; // "Doe"

Constructor function

πŸ‘‰ Useful to create multiple objects with the same properties and methods

πŸ‘‰ Function Name should be capitalized (convention)

πŸ‘‰ Use of the newΒ keyword

Closure

function add(a) {
  return function(b) {
    return a + b;
  }
}

const add10 = add(10); // add10 is a closure

add10(1); // 11
add10(2); // 12

add10 is a closure because it remembersΒ the environment in which it was created, when used later

6. Control structures

if / else

if (a > 10) {
  // do something
} else if (a > 5) {
  // do something else
} else {
  // do something else, again
}

In if (condition), condition is considered to be either truthy of falsy

switch

switch (color) {
  case 'RED':
    // do something when color === 'RED'
    break;
  case 'BLUE':
    // do something when color === 'BLUE'
    break;
  default:
    // do something when color is not 'RED' or 'BLUE'
}

switch

switch (x) {
  case 1:
    console.log(1);
    break;
  case 2:
    console.log(2);
  default:
    console.log(-1);
}

Here, what happens if x = 2?

⚠️ 2 and -1 will be printed because break is missing!

for loop

const names = [ 'Alice', 'Bob', 'John' ];

for (let i = 0; i < names.length; i++) {
  console.log(names[i]);
}

>> Alice
>> Bob
>> John

Old school way... πŸ™ˆ

for loop

const names = [ 'Alice', 'Bob', 'John' ];

for (let name of names) {
  console.log(name);
}

>> Alice
>> Bob
>> John

for ... of: better! πŸ˜‰ (ES2015)

while loop

let n = 0;
let x = 0;

while (n < 3) {
  n++;
  x += n;
}

// x = ?

The loop executes itself until the condition evaluates to false

let n = 0;
let x = 0;

while (n < 3) {
  n++;
  x += n;
}

// x = 6

7. Data structures

Object

Object litteral syntax

const book = {}; // Empty object
const book = { // Or with properties
  title: 'A Game of Thrones',
  published: new Date('August 1, 1996'),
  author: {
    name: 'George R. R. Martin'
  }
};

Object

Set properties

book.title = 'A Clash of Kings';
// or
book['title'] = 'A Clash of Kings'
// Nested property
book.author.birth = new Date('September 20, 1948');

⚠️ TypeError if author is not defined (needs to be at least an empty object)

Object

Get properties

const bookTitle = book.title;
// or book['title']

const authorName = book.author.name;
// or book['author']['name']

console.log(bookTitle); // A Clash of Kings
console.log(authorName); // George R. R. Martin

Object

Destructuring (ES2015)

const { title } = book;
const { name } = book.author;

console.log(title); // ? 
console.log(name); // ?
const { title } = book;
const { name } = book.author;

console.log(title); // A Clash of Kings
console.log(name); // George R. R. Martin

Array

// Empty array creation
const emptyArray = [];

// Array creation with elements
const names = [ 'Alice', 'Bob', 'John' ];

console.log(names.length); // 3

An Array is a list-like object

⚠️ length property is not fixed and can be changed any time

Array

const names = [ 'Alice', 'Bob', 'John' ];

names[0]; // "Alice"
names[1]; // "Bob"

// Get last element
names[names.length - 1]; // "John"

Accessing elements

Array

const names = [ 'Alice', 'Bob', 'John' ];

const [alice] = names;
console.log(alice); // Alice 

const [, , john] = names;
console.log(john); // John

Destructuring (ES2015)

Array

const items = [ 'Alice', 'Bob', 'John' ];

items[2] = 'Jane';
items.push(100);

console.log(items); // ?

Setting elements

const items = [ 'Alice', 'Bob', 'John' ];

items[2] = 'Jane';
items.push(100);

console.log(items); // ["Alice", "Bob", "Jane", 100]

Array

const names = [ 'Alice', 'Bob', 'John' ];

names.forEach(name => {
  console.log(name);
});

>> Alice
>> Bob
>> John

Array.prototype.forEach

Loop through items, does not return anything

Array

const names = [ 'Alice', 'Bob', 'John' ];

const fnames = names
  .filter(name => name.length > 3);

console.log(fnames); // ["Alice", "John"]

Array.prototype.filter

Returns a new array where each items verifies the given condition

Array

const names = [ 'Alice', 'Bob', 'John' ];

const newNames = names
  .map(name => name.substring(0, 2));

console.log(newNames); // ["Al", "Bo", "Jo"]

Array.prototype.map

Returns a new array with transformed items

Array

const numbers = [ 1, 2, 3 ];

const sum = numbers
  .reduce((total, number) => total += number);

console.log(sum); // 6

Array.prototype.reduce

Returns a single value by applying an accumulator function to each items (reducing)

8. Type Coercion &

Falsy / Truthy values

Type coercion

Implicit conversion from a type to anotherΒ 

const foo = '1';
const bar = 1;

foo == bar // true, coercion!

foo === bar // false

Type coercion

Implicit conversion to stringΒ 

const ten = 10;
const thousand = '1000';

ten + thousand // ?

const ten = 10;
const thousand = '1000';

ten + thousand // "101000"

Type coercion

Implicit conversion to stringΒ 

const names1 = [ 'Alice', 'Bob' ];
const names2 = [ 'John', 'Jane' ];

names1 + names2 // ?

const names1 = [ 'Alice', 'Bob' ];
const names2 = [ 'John', 'Jane' ];

names1 + names2 // "Alice,BobJohn,Jane"

Type coercion

Implicit conversion to stringΒ 

const hundred = '100';
const truthy = true;

hundred + truthy // ?

const hundred = '100';
const truthy = true;

hundred + truthy // "100true"

Type coercion

Implicit conversion to numberΒ 

const five = 5;
const four = '4';

five - four // ?

const five = 5;
const four = '4';

five - four // 1

Type coercion

Implicit conversion to numberΒ 

const five = 5;
const four = [ 4 ];

five - four // ?

const five = 5;
const four = [ 4 ];

five - four // 1

Type coercion

Implicit conversion to numberΒ 

const five = 5;
const numbers = [ '1', '2', '3' ];

five - numbers // ?

const five = 5;
const numbers = [ '1', '2', '3' ];

five - numbers // NaN

Type coercion

Implicit conversion to numberΒ 

const five = 5;
const falsy = false;

five - falsy // ?

const five = 5;
const falsy = false;

five - falsy // 5

Type coercion

Implicit conversion to booleanΒ 

const foo = 'foo';
const ten = 10;

foo || ten // ?

const foo = 'foo';
const ten = 10;

foo || ten // "foo"

When using || πŸ‘‰ if the first value casts to true, then it is returned

Type coercion

Implicit conversion to booleanΒ 

function hello(name) {
  return `Hello, ${name || 'Anonymous'}`;
}

hello('John'); // "Hello, John"
hello();       // "Hello, Anonymous"

Type coercion

Implicit conversion to booleanΒ 

const foo = 'foo';
const ten = 10;

foo && ten // ?

const foo = 'foo';
const ten = 10;

foo && ten // 10

When using && πŸ‘‰ if both values cast to true, then second one is returned, else first falsyΒ value is returned

Falsy values

if (false)
if (null)
if (undefined)
if (0)
if (NaN)
if ('')
if ("")
if (document.all) // Legacy, browser detection

Truthy values

EVERYTHING

ELSE

9. this keyword

Global context

this

console.log(this); // Window { ... }

var one = 1;

console.log(window.one); // 1
console.log(this.one); // 1

this.two = 2;

console.log(two); // 2
console.log(window.two); // 2

Inside a function

this

function add(a, b) {
  return a + b + this.c;
}

var c = 3;
add(1, 2); // 6

add is called within global context

Inside a function

this

function add(a, b) {
  return a + b + this.c;
}

var c = 3;

const obj = { c: 4 };

add.call(obj, 1, 2); // ?
// or add.apply(obj, [1, 2]);

add is called within obj context (πŸ’‘call:Β columns,Β apply:Β array)

function add(a, b) {
  return a + b + this.c;
}

var c = 3;

const obj = { c: 4 };

add.call(obj, 1, 2); // 7
// or add.apply(obj, [1, 2]);

Object method

this

add is called within obj context

var a = 1;

const obj = {
  a: 2,
  add: function(b, c) {
    return this.a + b + c;
  }
}

obj.add(2, 3); // ?
var a = 1;

const obj = {
  a: 2,
  add: function(b, c) {
    return this.a + b + c;
  }
}

obj.add(2, 3); // 7

this

thisΒ is bound to the new object being constructed

function User(name) {
  this.name = name;
}

const john = new User('John Doe');
console.log(john.name); // John Doe

Constructor function

Arrow function

this

thisΒ retains the value of the enclosing lexical context's this

var a = 1;

const obj = {
  a: 2,
  add: (b, c) => {
    return this.a + b + c;
  }
};

obj.add(2, 3); // ?
var a = 1;

const obj = {
  a: 2,
  add: (b, c) => {
    return this.a + b + c;
  }
};

obj.add(2, 3); // 6

10. Prototypes

Every function has a prototype property

Prototypes

// Custom function
function Person(name) { this.name = name; }
Person.prototype // {}

// Built-in function
Array.prototype // { ..., pop: f, push: f, ... }

Property inheritance

Prototypes

Person.prototype.who = function() {
  return `I'm ${this.name}`;
}

const john = new Person('John');
const alice = new Person('Alice');

alice.who = function() {
  return `This is ${this.name}`;
}

john.who() // "I'm John"
alice.who() // "This is Alice"

All objects inherit properties and methods from their prototype

Protoype chain

Prototypes

When a property / method is called on an object, the search starts on the object's attributes. If it is found, then it is returned.

Β 

Otherwise, the search goes upward πŸ‘† to the prototype's attributes.

11. ES2015 classes

ES2015 classes are syntax sugar over prototype-based inheritance

class Person {
  constructor(name) {
    this.name = name;
  }

  who() {
    return `Hi, I'm ${this.name}`;
  }
}

ES2015 class

const john = new Person('John');

john.who(); // "Hi, I'm John"

console.log(john); // { name: "John" }
console.log(Person.prototype); // { who: f }

ES2015 class

class Developer extends Person {
  constructor(name, language) {
    super(name);
    this.language = language;
  }
}

const jane = new Developer('Jane', 'JavaScript');

jane.who(); // "Hi, I'm Jane"
console.log(jane.language); // JavaScript

ES2015 class

Subclassing with extends

12. ES2015 modules

πŸ‘‰ Encapsulates code into a single unit Β 

What's a module?

πŸ‘‰ 1 module per file / 1 file per module

πŸ‘‰ Export objects and functions so that they're available to other modules

// file foo.js
export default class {
  constructor() { ... }
}

export

default export

There can only be 1 default export per file

// file bar.js
export default function() { ... }
// file baz.js
export default { ... }
// file dev.js
export class Developer { ... }

export function hire(developer) { ... }

export const FMKS = [ 'React', 'Vue', 'Angular' ];

export

named export

There can be multiple named exports per file

import Foo from './foo.js';

import bar from './bar.js';

import baz from './baz.js';

import

Importing defaults

Foo, bar, baz can have any other names

import { Developer, hire, FMKS } from './dev.js';

import

Importing named exports

import * as dev from './dev.js';

const alice = dev.Developer('Alice', 'JavaScript');

dev.hire(alice);
alice.chooseFramework(dev.FMKS);

13. Handling DOM

πŸ‘‰ Document Object Model Β 

DOM

πŸ‘‰ Programming interface for HTML

πŸ‘‰ Represents the document (web page) as nodes and objects

DOM

HTML attribute vs DOM property

<h1 class="title hello">Hello, World!</h1>

πŸ‘‰ An attribute is always a string, its value is static (written in the HTML code)

h1.getAttribute('class'); // "title hello"

h1.className; // "title hello"
h1.classList; // [ "title", "hello" ]

πŸ‘‰ A property is not always a string, its value is dynamic

DOM

Creating an element

const h1 = document.createElement('h1');
h1.textContent = 'Hello, World!';

document.body.appendChild(h1);
<body></body>
<body>
  <h1>Hello, World!</h1>
</body>

DOM

Accessing an element

// Get element by type
const h1 = document.querySelector('h1');
<body>
  <h1>Hello, World!</h1>
</body>

πŸ‘‰ querySelector function takes a CSS selector as argument

DOM

Accessing an element

// Get element by id
const h1 = document.querySelector('#title');
<body>
  <h1 id="title">Hello, World!</h1>
</body>

DOM

Accessing an element

// Get element(s) by class
const lis = document.querySelectorAll('.name');
<ul>
  <li class="name">John</li>
  <li class="name">Jane</li>
  <li class="name">Alice</li>
</ul>

DOM

Accessing an element

// Get element by attribute
const input = document
  .querySelector('[name="search"]');
<input name="search">

DOM

Accessing the parent element

const h1 = document.querySelector('#title');
const div = h1.parentElement;
<body>
  <div class="greetings">
    <h1 id="title">Hello, World!</h1>
  </div>
</body>

DOM

Accessing the children elements

const div = document.querySelector('.greetings');
const h1 = div.firstElementChild;
<div class="greetings">
  <h1>Hello, World!</h1>
  <h2>My name is John</h2> 
</div>

DOM

Accessing the children elements

const div = document.querySelector('.greetings');
const h2 = div.lastElementChild;
<div class="greetings">
  <h1>Hello, World!</h1>
  <h2>My name is John</h2> 
</div>

DOM

Accessing an element sibling

const h1 = document.querySelector('h1');
const h2 = h1.nextElementSibling;
<div class="greetings">
  <h1>Hello, World!</h1>
  <h2>My name is John</h2> 
</div>

DOM

Accessing an element sibling

const h2 = document.querySelector('h2');
const h1 = h2.previousElementSibling;
<div class="greetings">
  <h1>Hello, World!</h1>
  <h2>My name is John</h2> 
</div>

DOM

Removing an element

const h1 = document.querySelector('h1');
h1.remove();
<body>
  <h1>Hello, World!</h1>
</body>
<body></body>

14. Asynchronous

πŸ‘‰ User interactions

πŸ‘‰ Ajax requests

πŸ‘‰ setTimeout, setInterval

Asynchronous stuff in JS

⚠️ JavaScript is single threaded (in the browser)

Asynchronous

Callback (user interactions)

window.addEventListener('click', $event => {
  console.log($event.clientX, $event.clientY);
});
// or
window.onclick = $event => {
  console.log($event.clientX, $event.clientY);
};

A callback is a function passed into another function as an argument

Asynchronous

Callback (user interactions)

const logEventPosition = $event => {
  console.log($event.clientX, $event.clientY);
}
// function logEventPosition($event) { ... }

window.addEventListener('click', logEventPosition);
// or
window.onclick = logEventPosition;

logEventPosition is the callback function

Asynchronous

Callback (ajax request)

$.ajax('http://localhost:8080/tv-shows')
 .done(tvShows => { // callback
   console.log(`success, tvShows = ${tvShows}`);
 })
 .fail(() => { // callback 
   console.log('error');
 })
 .always(() => { // callback
   console.log('complete');
 });

Asynchronous

Callback (setTimeout)

setTimeout(() => {
  console.log(`I'm 1 second late`); 
}, 1000);

// or
const message = () => { // function message() { ... }
  console.log(`I'm 1 second late`);
};
setTimeout(message, 1000);

Asynchronous

Callback Hell 😈

setTimeout(() => {
  setTimeout(() => {
    setTimeout(() => {
      setTimeout(() => {
        console.log(`I'm 4 seconds late!`);
      }, 1000);
    }, 1000);
  }, 1000);
}, 1000);

Asynchronous

Callback Hell 😈

function timeout1() { setTimeout(timeout2, 1000); }
function timeout2() { setTimeout(timeout3, 1000); }
function timeout3() { setTimeout(timeout4, 1000); }
function timeout4() {
  setTimeout(() => {
    console.log(`I'm 4 seconds late!`);
  }, 1000);
}

timeout1();

Better use functions ✌️

Asynchronous

Promise

Completion (or failure) of an async operation and its resulting value

πŸ‘‰ Pending / Resolved / Rejected

Asynchronous

Promise / then()

fetch('/api/names').then(response => {
  // Promise was resolved
  if (response.status === 200) {
    ...
  }
}, error => {
  // Promise was rejected
  console.error(error);
});

Here, the Promise object is returned by fetch() function call

Asynchronous

Promise / catch()

fetch('/api/names')
  .then(response => {
    throw new Error('Ugh!');
  })
  .catch(error => {
    // Promise was rejected
    console.error(error);
  });

.catch() is another way of dealing with Promise rejection

Asynchronous

Chaining promises

function toUpperCase(names) { ... }

fetch('/api/names')
  .then(response => response.json())
  .then(data => {
    const { names } = data; // [ "John", "Jane" ]
    return toUpperCase(names);
  })
  .then(names => {
    console.log(names); // [ "JOHN", "JANE" ]
  });

Asynchronous

Creating a Promise...

function getBurgers() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('πŸ”πŸ”πŸ”');
    }, 1000);
  });
}

getBurgers().then(burgers => {
  // After 1 second
  console.log(burgers); // πŸ”πŸ”πŸ”
});

...that will be resolved after 1 second

Asynchronous

Creating a Promise...

function getBurgers() {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject('πŸ†πŸ†πŸ†');
    }, 1000);
  });
}

getBurgers().then(() => {}, eggplants => {
  // After 1 second
  console.log(eggplants); // πŸ†πŸ†πŸ†
});

...that will be rejected after 1 second

Asynchronous

Promise.all()

const promise1 = Promise.resolve(1);
const promise2 = Promise.resolve(2);
const promise3 = Promise.resolve(3);

Promise
  .all([promise1, promise2, promise3])
  .then(responses => {
    console.log(responses); // [1, 2, 3]
  });

Promise.all() function returns a single promise that's resolved when all promises passed as an Array are resolved

Asynchronous

async / await (ES2017)

function getBurgers() { return new Promise(...); }
function getBeers() { return new Promise(...); }

async function menu() {
  const burgers = await getBurgers();
  const beers = await getBeers();
  console.log(burgers, beers); // πŸ”πŸ”πŸ”, 🍺🍺🍺
}
menu();

Allow async code to be handled in a synchronous way

Asynchronous

async / await (ES2017)

function getBurgers() { return new Promise(...); }

async function menu() {
  try {
    const burgers = await getBurgers();
  } catch (eggplants) {
    console.log(eggplants); // πŸ†πŸ†πŸ†
  }
}
menu();

Errors are handled with try ... catch block

15. Ecosystem /

tools & libraries

A JavaScript utility library

THE package manager for JavaScript

Fast, reliable and secure dependency management

The compiler for writing next generation JavaScript

Module bundler: bundle JavaScript files for usage in the browser

Modern JavaScript

By Nicolas Payot

Modern JavaScript

  • 1,883