Variables and functions:
-
Start with a letter, underscore
_, or dollar sign$. -
I can use letter/numbers/underscores/dollar sign $.
-
I don't have to use
camelCaseand I can use car2go it's fine. But camelCase is preferred. -
They are case sensitive.
-
When a var begins with
_means it shouldn't be freely altered. (private)
Classes:
CamelCase
- 0
- ""/'' Empty strings
- null
- undefined (Un-initialized vars)
- NaN (Not a Number)
if () {
//code
} else if () {
//code
} else {
//code
}let defaultName = username || 'Stranger'; //if username false, nome = StrangerisOffTime ? letsGoHome() : keepWorkingHard();let groceryItem = 'papaya';
switch (groceryItem) {
case 'tomato':
console.log('Tomatoes are $0.49');
break;
case 'lime':
console.log('Limes are $1.49');
break;
case 'papaya':
console.log('Papayas are $1.29');
break;
default:
console.log('Invalid item');
break;
}Template literals:
let name = "Lucia";
console.log(`My name is ${name}.`); //use backtick to print var inlinefunction addNumbers(x, y){
return x + y;
} //traditional function, no semicolonI don't name the function, and I store it in a variable (commonly a const), in this way, the function won't be constructed at compile time, instead it gets initialized at runtime when I initialize the variable in which it's stored. I save time and space.
const calculateArea = function(width, height) {
const area = width * height;
return area;
};
const rectangleArea = (width, height) => {
let area = width * height;
return area;
};To use the function Expression use the const name: calculateArea(5, 7);.
/* Omitting () for one parameter */
//zero parameters
const functionName = () => {};
//one parameter
const functionName = paramOne => {};
//two or more parameters
const functionName = (paramOne, paramTwo) => {};/* Omitting return and {} for single-line block */
//single-line block
const sumNumbers = number => number + number; //no need to write "return"
//multi-line block
const sumNumbers = number => {
const sum = number + number;
return sum; //two lines, yes "return".
};If the parameter is undefined or no argument is passed.
function greeting(name = 'Stranger'){
console.log(`Hello, ${name}!`);
}function avg(...args){
var sum = 0;
for (let value of args){
sum += value;
}
return sum/args.length;
}I create a closure whenever I declare a function inside another function. The father function's variables stay alive (inaccessible to user) until the child function is not accessible anymore, because the child function often depends on these variables.
var breakfast = ["coffee", "croissant"];
var many_types = ["string", 123, true, ["array", "inside"]];
breakfast[breakfast.length-1]; //access last element- .length //returns the length of the array
- .concat(array a) //returns a new array, with a concatenated
- .pop() //removes the last element
- .push(element e) //adds e as the last element
- .reverse() //returns the array, reversed
Index out of range: undefined.
I can always iterate using the for keyword:
for (let i = 0; i < arr.length; i++){
//Do something with arr[i]
}for (const currentValue of arr) {
//Do something with currentValue
}I can also use array's iterator methods that help me iterate over them:
.forEach()does something for each element. Returns undefined.
let games = ['SAO', 'LZBW', 'PKM'];
games.forEach(game => {
console.log("I don't have enough money to buy "+game+".");
});.map()creates a new array, mutating every item.
const numbers = [1,2,3,4,5];
const squares = numbers.map(number => {
return number*number;
});.filter()creates a new array with all elements that pass the test.
const words = ['elite', 'exuberant', 'day', 'hi'];
const shortWords = words.filter(word => {
return word.length < 5;
});.findIndex()returns the index of the first element that passes the test.
const words = ['elite', 'exuberant', 'day', 'hi'];
const shortWords = words.filter(word => {
return word.length < 5;
}); //2.reduce()returns one single value after iterating through the elements.
const array1 = [1, 2, 3, 4];
const reducer = (accumulator, currentValue) => accumulator + currentValue;
// 1 + 2 + 3 + 4
console.log(array1.reduce(reducer));
// expected output: 10
// 5 + 1 + 2 + 3 + 4
console.log(array1.reduce(reducer, 5));
// expected output: 15let car2go = {
name: "car sharing",
id: 6741,
available: true,
'Fuel Type': 'diesel'
};If the reference name has special characters (space etc.), I enclose it with quotation marks.
let car2go = {
id: 6741,
fuelLevel: 80,
reFuel () {
this.fuelLevel = 100;
}
};Functions that get an object as a parameter and then reassign its properties, work. If they reassign the object, they don't work.
If I have to use this in a method, do not use arrow functions.
let car2go = {
_fuelLevel: 80,
get fuelLevel () { //Remember the `get` keyword
if (this._fuelLevel) {
return this.fuelLevel;
} else {
return null;
}
},
reFuel () {
this.fuelLevel = 100;
}
};let car2go = {
_fuelLevel: 80,
get fuelLevel () { //Remember the `get` keyword
if (this._fuelLevel) {
return this.fuelLevel;
} else {
return null;
}
},
set _fuelLevel (level) {
if (level) {
this._fuelLevel = level;
} else {
console.log('nah');
};
}
};car2go.id;
car2go["id"];let car2go = {
id: 6741
}
const {id} = car2go; //var name should be the same of the property keyMath.random(); //Random number between 0 and 1
Math.random() * 99; //Random number between 0 and 99
Math.floor(0.8945); //Round the number to the closest whole numberObject.keys(obj)returns and array of obj's property keys.
const car2go = {
id: 154,
name: 'Charlie'
}
Object.keys(car2go); //['id','name']Object.entries(obj)returns an array of obj's properties [key, value] pairs.
const car2go = {
id: 154,
name: 'Charlie'
}
Object.entries(car2go); //[['id',154],['name','Charlie']] /*Order is not guaranteed*/Object.assign(target, source)copies all source's properties and merges it with target's, mutating it.
const car2go = {
id: 154,
name: 'Charlie'
}
const car3go = {
id: 166,
isFree: true
}
let assigned = Object.assign(car2go, car3go);
//car2go = {id:166, name:'charlie', isFree: true}
//assigned = {id:166, name:'charlie', isFree: true}If I want to keep target the way it is, I have to use Object.create(target) .
Object.create(obj)creates a new object copy of the obj.
const car2go = {
id: 154,
name: 'Charlie'
}
let copy = Object.create(car2go);
//copy = {id:154, name:'Charlie'}let letters = {
a: 1,
b: 2,
z: 26
};
for (let letter in letters) { //loops on properties
console.log(letter); //a b c
console.log(letters[letter]); //1 2 26
};letter is the properties' key, to access the values, I have to use obj[property].
const factory = (id, isOk) => {
return { //returns an object
id,
isOk
}
};class Cat {
//special method that creates the object
constructor(name){
this._name = name; //these are the properties
this._favoriteFoods = [];
}
get name(){
return this._name;
}
get favoriteFoods(){
return this._favoriteFoods; //!!! Reference is returned, may not be safe.
}
addFavoriteFood(food){
this._favoriteFoods.push(food);
return food;
}
}class Cat { ... }
let sachi = new Cat('Sachi'); //a new Cat object with name = 'Sachi'class Animal {
constructor(name){
this._name = name;
this._favoriteFoods = [];
}
get name(){}
get favoriteFoods(){}
}
class Cat extends Animal {
constructor(name, usesLitter){
super(name);
this._usesLitter = usesLitter;
}
}
let sachi = new Cat('Sachi', usesLitter);
sachi.name //SachiI use these if I have to call a method from the class itself and not from an object of the class.
class Animal {
constructor(name){
this._name = name;
this._favoriteFoods = [];
}
get name(){}
get favoriteFoods(){}
static generateName () { //returns a random element from listNames list
const listNames = ['a', 'b', 'c'];
return listNames[Math.floor(Math.random()*listNames.length)];
}
}
Animal.generateName //a / b / c- Export the module (ES5):
let Airplane = {
type: "StarJet",
showTyp: function () {
console.log(this.type);
}
};
module.exports = Airplane;- Import it in another file (ES5):
const Plane = require('./airplane.js') //import from file
function showType() {
console.log(Plane.type);
}
showType(); //"StarJet"
Plane.showTyp(); //"StarJet"- export default:
const Cat = {
name: 'Sachi',
isCute: true
};
export default Cat; //same as module.exports = Cat;- import:
import sachi from './cat'
//sachi is now my variable for Cat module
console.log(sachi.isCute); //true- named export:
let nameList = ['a', 'b', 'c'];
let num = 4;
export {nameList, num}; //export later
export let keys = [1, 2, 3]; //export at once- named export as:
export {nameList as people, num as quota};- named import:
import {nameList, num} from './cat'
console.log(nameList[0]); //'a'
console.log(num); //4- named import as:
import {nameList as people} from './cat'
import * as Cat from './cat';
Cat.name; //'Sachi'- Mixing these up:
export let foods = '';
function isVeg() {
};
function isLow() {
};
function isGFree() {
};
export {isVeg as veg};
export default isGFree;import {foods, isVeg} from './menu';
import isGFree from './menu';Promises are special objects. When executed, the pending state (initial state) is changed to resolved or rejected.
let isHappyDay = false;
const someExecutor = (resolve, reject) => {
if (isHappyDay) {
resolve('Success message!');
} else {
reject('Reject message!');
};
};
let myPromise = new Promise(someExecutor); //Executes someExecutor
console.log(myPromise); //'Reject message!'setTimeout(function, timeout) waits at least timeout milliseconds, then executes the function.
function printOne(){
console.log('1');
};
setTimeout(printOne, 2000);
//After at least 2 seconds, '1' is printed
const makePromise = () => {
return new Promise((resolve, reject) => {
setTimeout( () => {resolve('I will make a Promise!')}, 1000);
});
};
const promised = makePromise();When a promise is settled, I can use .then(onFulfilled, onRejected). The arguments are functions, handlers of the settled value.
const myNumber = Math.random()*999999;
let lottery = new Promise((resolve, reject) => {
let num = Math.random()*999999;
if (myNumber===num){
resolve("I'll buy everything.");
} else {
reject("Keep working!");
};
});
const handleWin = (winMessage) {
console.log(winMessage);
myNumber = Math.random()*999999;
playAgain();
};
const handleLost = (loseMessage) => console.log(loseMessage);
lottery.then(handleWin, handleLost);This is the same thing as then except it accepts only one argument: onRejected. We can use then and catch to write clearer code:
prom
.then((resolvedValue)=>{
console.log(resolvedValue);
})
.catch((rejectionReason)=>{
console.log(rejectionReason);
});I can chain multiple promises, using then in chain:
let ok = true;
const startWashing = (clothes) => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
ok? resolve(clothes) : reject('nope');
}, 500);
});
}
const startDrying = (clothes) => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
ok? resolve(clothes) : reject('nooope');
}, 500);
});
}
const foldClothes = (clothes) => {
return new Promise((resolve, reject)=>{
setTimeout(()=>{
ok? resolve(clothes) : reject('nooooooooope');
}, 500);
});
}
function putOnClothes = (clothes) => {
console.log('Put those on!!!');
};
function burnEverything = (clothes) => {
console.log('I burnt everything :>');
}
//When everything should be done in order
startWashing(myClothes) //returns a promise
.then((washedClothes) => {
return startDrying(washedClothes);
})
.then((dryedClothes)=>{
return foldClothes(dryedClothes);
})
.then(putOnClothes, burnEverything);The variable clothes is automatically passed on through the chain if promises are successfully resolved, otherwise the error message is passed on.
Promise.all([promise1, promise2])
I let all promises start together, if everything returns ok, Promise.all() returns an array of resolved values, otherwise returns the first reject reason and stops (failing fast).
let myPromises = Promise.all([promise1, promise2]);
myPromises
.then((arrayOfOks)=>{
console.log(arrayOfOks);
})
.catch((errorMessage)=>{
console.log(errorMessage);
});I use async keyword to write functions that handle asynchronous actions.
async functions always return a promise:
- The function returns nothing: promise with resolved value = undefined.
- The function returns a non-promise value: promise with resolved value = value.
- The function return a promise: promise.
async function myFunc(){
//yadayadayada
};
const myFunc = async () => {
//yadayadayada
};
myFunc();It can only be used inside an async function; it is an operator, pauses the async function until a given promise is resolved and returns the resolved value.
const makePromise = () => {
return new Promise((resolve, reject) => {
setTimeout( () => {resolve('I will make a Promise!')}, 1000);
});
};
async function waitForPromise() {
let promised = await makePromise(); //waits for it to finish promising
console.log(promised); //'I will make a Promise!'
}
async function waitForAll() {
let promises = await Promise.all([makeOne(), makeTwo(), makeThree()]);
}If I don't put await in an async function, it can be executed before we expected, getting an unresolved promise in the "pending" state.
It's nice if we add await to vars only the moment they're used and not when they're declared. In this way all the async functions start to run, and I wait only if I need to and only for the one I need.
async function hello(){
let promised = makePromise();
console.log(await promised);
}I use try ... catch to catch errors in async ... await functions.
async function catchingErrors() {
try {
let resolvedValue = await asyncFunction();
} catch (errorMessage) {
console.log(errorMessage)
}
}AJAX or Asynchronous JavaScript and XML allows me to load a web page in an asynchronous way, ie. loading texts and images together.
XMLHttpRequest (XHR) is the tool to accomplish requests.
const xhr = new XMLHttpRequest();
const url = 'https://api-to-call.com/endpoint';
xhr.responseType = 'json'; //"" or arraybuffer or blob or document or json or text
xhr.onreadystatechange = ( () => {
if (xhr.readyState === XMLHttpRequest.DONE) { //check if req is finisced
return xhr.response;
}
});
xhr.open('GET', url); //open request
xhr.send(); //send requestconst xhr = new XMLHttpRequest();
const url = 'https://api-to-call.com/endpoint';
const data = JSON.stringify({id: '200'}); //setting params
xhr.responseType = 'json';
xhr.onreadystatechange = ( () => {
if (xhr.readyState === XMLHttpRequest.DONE){
return xhr.response;
};
});
xhr.open('POST', url);
xhr.setRequestHeader('Content-type', 'application/json');
xhr.setRequestHeader('apikey', apiKey);
xhr.send(data); //send params hereIt uses promises to handle requests; creates a request object with needed query, sends the request, returns the response as a promise.
fetch('https://api-to-call.com/endpoint')
.then((response) => { //first then ok
if (response.ok){
return response.json();
}
throw new Error('Request failed!');
}, (networkError) => { //first then not-ok
console.log(networkError.message);
})
.then((jsonResponse) => { //second then
return jsonResponse;
});const shortenUrl = () => {
const urlToShorten = inputField.value; //query
const data = JSON.stringify({destination: urlToShorten}); //post data
fetch(url, {method: 'POST', //specify post, headers and body
headers: {
'Content-type': 'application/json',
'apikey': apiKey
},body: data})
.then((response)=>{
if (response.ok) {
return response.json();
}
throw new Error('Request failed!');
}, (networkError) => {
console.log(networkError.message);
})
.then((jsonResponse)=>{
renderResponse(jsonResponse);
})
}const getSuggestions = async () => {
const wordQuery = inputField.value;
const endpoint = url + queryParams + wordQuery;
try {
const response = await fetch(endpoint, {cache: 'no-cache'});
if (response.ok) {
const jsonResponse = await response.json();
renderResponse(jsonResponse);
}
} catch(error) {
console.log(error);
}
}const shortenUrl = async () => {
const urlToShorten = inputField.value;
const data = JSON.stringify({destination: urlToShorten}); //input data
try {
const response = await fetch(url, {method: 'POST',
body: data,
headers:{
'Content-type': 'application/json',
'apikey': apiKey}});
if (response.ok) {
const jsonResponse = await response.json();
renderResponse(jsonResponse);
}
} catch(error){
console.log(error);
}
}