Skip to content

Instantly share code, notes, and snippets.

@kzhangkzhang
Last active February 22, 2024 20:49
Show Gist options
  • Save kzhangkzhang/3bc6e411357c0329c3e342ad496367d0 to your computer and use it in GitHub Desktop.
Save kzhangkzhang/3bc6e411357c0329c3e342ad496367d0 to your computer and use it in GitHub Desktop.
Cheat sheet for modern (ES6) Javascript, part A

Modern JavaScript Cheat Sheet - Part A

Support\Web_Cloud\WEB_Javascript_A.md

Constant

  • Constant must be initialized and value can't be changed (for primitive type)
  • By convention, constant variable shuold be UPPERCASE
// Example 1
const CAR_ID = 42;
const BODY_STYLE;        // error! need initialization

CAR_ID = 100;            // error! can't change value

// Example 2: constant has block scope
const CRUISE_DAYS = 7;
if (CRUISE_DAYS > 5) {
    const CRUISE_DAYS = 30;
}
console.log(CRUISE_DAYS);   // 7

Let and Var

Please read this thread to understand

  • 'var' variables are ‘function scope.’ What does this mean? It means they are only available inside the function they’re created in, or if not created inside a function, they are ‘globally scoped.’
  • 'let' and 'const' variables are scoped to the block
    • what is the block? A block is a set of opening and closing curly brackets

Recap

  • var is function scope

  • let and const are block scope

  • Function scope is wihtin the function

  • Block scope is within curly brackets

// Example 1a: ES5 **hoisting (竖起)** for "var"
console.log(carId); // undefined (not an error);
var carId = 4;

// Example 1b: ES6 let
console.log(carId); // ReferenceError;
let carId = 4;

// Example 1c: ES6 let
let carId;
console.log(carId); // undefined

// Example 2
if (true) {
  var foo = 9;
}
console.log(foo); // 9

if (true) {
  let foo = 9;
}
console.log(foo); // error!

// Example 3a: let has block scope
let daysBeforeCruise = 10;
{
  let daysBeforeCruise = 5;
}
console.log(daysBeforeCruise); // 10

// Example 3b: let has block scope
{
  let daysBeforeCruise = 5;
}
console.log(daysBeforeCruise); // ReferenceError

// Example 3d:
function updateCruiseDate() {
  cruiseDate = "22-DEC-2018";
}

let cruiseDate = null;
updateCruiseDate();
console.log(cruiseDate); // 22-DEC-2018

// Example 3e:
let noCruiseDays = 7;

for (let noCruiseDays = 0; noCruiseDays < 100; noCruiseDays++) {}
console.log(noCruiseDays); // 7

// Example 4a: ES5 "var" has global scope
let updateFunc = [];
for (var i = 0; i < 2; i++) {
  updateFunc.push(function() {
    return i;
  });
}
console.log(updateFunc[0]); // f () {return i;}
console.log(updateFunc[0]()); // 2    ==> most likely, this is unexpected result

// Example 4b: ES6 "let" has block scope
let updateFunc = [];
for (let i = 0; i < 2; i++) {
  updateFunc.push(function() {
    return i;
  });
}
console.log(updateFunc[0]); // f () {return i;}
console.log(updateFunc[0]()); // 0  ==> most likely, this is expected result

Rest Parameters: ...theRest

It allows us to represent an indefinite number of arguments as an array

// Example 1
function sendCars1(...allCarIds) {
  allCarIds.forEach(id => console.log(id));
}

sendCars1(100, 200, 300); // 100 200 300

// Example 2: named parameter (day) + Rest Parameter
// In such case, Rest Parameter must be **LAST** in the list

function sendCars2(day, ...allCarIds) {
  allCarIds.forEach(id => console.log(id));
}

sendCars2('Monday', 100, 200, 300); // 100 200 300

// Example 3: there is another parameter (anotherDay)
// after Rest Parameter ==> this is **syntax error**

function sendCars3(day, ...allCarIds, anotherDay) {
  allCarIds.forEach(id => console.log(id));
}

sendCars3('Monday', 100, 200, 300); // Error!

Destructing

Destructuring is a JavaScript expression that makes it possible to unpack and assign values from arrays, or properties from objects, into distinct variables.

Destructuring Arrays [a,b] = arr

To destruct array, variables on left assignment need within []

below is just some common examples, please read this for more cases

// Example 1
let carIds = [1, 2, 5];
let [car1, car2, car3] = carIds;

console.log(car1, car2, car3); // 1 2 5

// Example 2a
let introduction = ["Hello", "I", "am", "Kevin"];
let [greeting, pronoun] = introduction;

console.log(greeting); //"Hello"
console.log(pronoun); //"I"

// Example 2b
let [greeting, pronoun] = ["Hello", "I", "am", "Sarah"];

console.log(greeting); //"Hello"
console.log(pronoun); //"I"

// Example 2c: skipping items in an Array
let [greeting, , ,name] = ["Hello", "I", "am", "Kevin"];

console.log(greeting); //"Hello"
console.log(name); //"Kevin"

// Example 3a
// Please notice: restFamilies is an array variable
let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];
let myFamily, restFamilies;
[myFamily, ...restFamilies] = cruiseFamilies;
console.log(myFamily, restFamilies); // Kevin ["Gang", "Eric", "Kong", "Song"]

// Example 3b: skip the first array element
// Please notice: restFamilies is an array variable
let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];
let restFamilies;
[, ...restFamilies] = cruiseFamilies;
console.log(restFamilies); // ["Gang", "Eric", "Kong", "Song"]

// Example 3c: skip the first and 2nd array element
// Please notice: restFamilies is an array variable
let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];
let restFamilies;
[, , ...restFamilies] = cruiseFamilies;
console.log(restFamilies); // ["Eric", "Kong", "Song"]

// Example 3d: skip the first, assign 2nd element to a variable and assign rest to an array variable
// Please notice: restFamilies is an array variable
let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];
let myFamily, myBestFriend, restFamilies;
[, myBestFriend, ...restFamilies] = cruiseFamilies;
console.log(myBestFriend, restFamilies); // Gang ["Eric", "Kong", "Song"]

// Example 4: Swapping Values using Destructuring Assignment
let a = 3;
let b = 6;

[a, b] = [b, a];

console.log(a); //6
console.log(b); //3

Destructing Objects: ({a,b} = obj)

To destruct object, variables on left assignment need within {}

below is just some common examples, please read this for more cases

// Example 1a: both variables (myBrand, myColor) are undefined
// because the variable **name doesn't match** to object's attribute.
// Basically, the variables in the object on the left hand side
// should have the same name as a property key in the object.
// If the names are different, we'll get undefined.
let car = { brand: "Acura-MDX", color: "black" };

let { myBrand, myColor } = car;
console.log(myBrand, myColor);  // undefined undefined

// Example 1b: variable names are matching to object attributes
//             this is expected result
let car = { brand: "Acura-MDX", color: "black" };

let { brand, color } = car;
console.log(brand, color);  // Acura-MDX black

// Example 1c: if we want to assign values of an object to a new
// variable instead of using name of the property, we will do below
// In below example, the values extracted are passed to the new
// variables myBrand and myColor
let car = { brand: "Acura-MDX", color: "black" };

let { brand: myBrand, color: myColor } = car;
console.log(myBrand, myColor); // Acura-MDX black

// Example 3a: Variables declared before being assigned
//             below 3rd line is syntax error because {}
//             is also used for code block. The compiler is
//             confused in this case. See 3b for soution
let car = { brand: "Acura-MDX", color: "black" };
let brand, color;
{ brand, color } = car;       // error!
console.log(brand, color);

// Example 3b: using () around the assignment statement is
// required syntax when using object literal destructuring
// assignment without a declaration.
let car = { brand: "Acura-MDX", color: "black" };
let brand, color;
({ brand, color } = car);
console.log(brand, color); // Acura-MDX black

// Example 4: address is an object within an object.
// pay attention how we extract street
let user = {
  name: "Kevin Zhang",
  age: 44,
  address: {
    street: "100 ABC Street",
    city: "Libertyville",
    state: "IL",
    zip: "60048"
  }
};

const { name, age, address: { city } } = user;

console.log(name, age, city); // Kevin Zhang 44 Libertyvillek

Destructing Misc

// Example: destruct string
let [firstLetter, lastLetter] = "AZ";
console.log(`first Letter: ${firstLetter} last Letter: ${lastLetter}`);
// first Letter: A last Letter: Z

Destructing Advanced

// Example 1a
let [low, high] = [,];
console.log(`low is ${low} and high is ${high}`);
// low is undefined and high is undefined

// Example 1b: destructing requires an iterate object.
// "undefined" is not iterable
let [low, high] = undefined; // Syntax error: TypeError: undefined is not iterable
console.log(`low is ${low} and high is ${high}`);

// Example 1c: destructing requires an iterate object.
// "null" is not iterable
let [low, high] = null; // Syntax error: TypeError: null is not iterable
console.log(`low is ${low} and high is ${high}`);

// Example 1d: there is a comma after "high". this is ok
let [low, high, ] = [10, 20];
console.log(`low is ${low} and high is ${high}`); // low is 10 and high is 20

// Example 2a: destructing in "for x of y" loop
for (let [a, b] of [[1, 2], [3, 4]]) {
  console.log(`a is ${a} b is ${b}`);
}
// a is 1 b is 2
// a is 3 b is 4

Spread Syntax: fun(...arr)

allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Read more about Spread

// Example 1

function startCruise(f1, f2, f3, f4, f5) {
  console.log(f1, f2, f3, f4, f5);
}

let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];

startCruise(...cruiseFamilies); // Kevin Gang Eric Kong Song

// Example 2: using spread and rest together
function startCruise(f1, f2, ...restFamilies) {
  console.log(f1, f2, restFamilies);
}

let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];

startCruise(...cruiseFamilies); // Kevin Gang ["Eric", "Kong", "Song"]

// Example 3: creating new object by copying from existing one
const brandon = {age: 10, school: "Copeland"};

const elena = {...brandon};

elena.age = 7;

console.log(elena.age);     // 7
console.log(brandon.age);   // 10


let y2019_cruiseFamilies = [
  {"family_name": "Kevin", "family_size": 4, "cruise": "RCL" },
  {"family_name": "Eric", "family_size": 4, "cruise": "NCL" },
  {"family_name": "Gang", "family_size": 3, "cruise": "NCL" },
  {"family_name": "Wei", "family_size": 4, "cruise": "NCL" }
];

const y2019_indexed_cruiseFamilies = y2019_cruiseFamilies.reduce(
  (acc, family) => ({...acc, [family.family_name]: family}), {}
)

// result
{ Kevin: { family_name: 'Kevin', family_size: 4, cruise: 'RCL' },
  Eric: { family_name: 'Eric', family_size: 4, cruise: 'NCL' },
  Gang: { family_name: 'Gang', family_size: 3, cruise: 'NCL' },
  Wei: { family_name: 'Wei', family_size: 4, cruise: 'NCL' } }

Type and Type conversion

  • JS is Dynamically Typed Language
    • Types are associated with values not variables
    • The same variables can hold multiple types
    • We do not need to specify types
    • Most other langueage are statically typed (Java, C#, C++, PLSQL)
    • There are supersets of JS and addons to allow static typing (TypeScript, FlowJS)

typeof()

typeof 100; // number
typeof true; // boolean
typeof "Kevin"; // string
typeof function() {}; // function
typeof {}; // object
// null is an object in C; Javascript roots from C
typeof null; // object, this is a bug. google 'typeof null is object" to read more
typeof undefined; // undefined
typeof NaN; // number
typeof Symbol()  //symbol, new ES6

Common Type Conversions

What is the difference between parseInt() and Number()?

// convert to string
let age = 44;
age.toString(); // "44"
String(age); // "44"
String(4+5); // "9"

// convert string to integer
Number.parseInt("0100"); // 100
Number.parseInt("0200AB"); // 200
Number.parseInt("A0200AB"); // NaN => if can't convert to a number
Number.parseInt("123.45"); // 123

// convert string to number
Number.parseFloat("12.345"); // 12.345
Number.parseFloat("12.345").toFixed(); // 12
Number.parseFloat("12.345").toFixed(1); // 12.3

// convert Boolean to string
let age2 = 44;
age2 = String(true); // "true"
console.log(age2.length); // 4
console.log((true).toString()); // "true"

// convert Boolean to number
console.log(Number(true)); // 1
console.log(Number(false)); // 0

// convert null to number
console.log(Number(null)); // 0

// convert date to string
let todayStr = String(new Date());
console.log(todayStr); // "Sun Apr 28 2019 13:51:49 GMT-0500 (Central Daylight Time)"
console.log(todayStr.length);  // 57

// convert array to string
console.log(String([1,2,3,4])); // "1,2,3,4"
console.log(String([1,2,3,4])); // 7

Operator

Equality Operators

== vs === != vs !==

== do implicit type conversion and then compare value === compare both type and value

1 == true; // true
1 === true; // false

let id = 123;

id == "123"; // true
id === "123"; // false

id != "123"; // false
id !== "123"; // true

Unary Operators

  • ++var1 var1++
  • --var1 var1--
  • +var1 -var1
let age = 44;
console.log(age++); // 44
console.log(age); // 45

let cruiseFamilies = 5;
console.log(++cruiseFamilies); // 6
console.log(cruiseFamilies); // 6

Logical Operators

Operator meaning
&& AND
|| OR
! reverse
// Example 1a: this is very common case
let userSettings = null;
let defaultSettings = {name: 'Default'};

console.log(userSettings || defaultSettings); // {name: "Default"}

// Example 1b: this is very common case
let userSettings = {name: "Kevin"};
let defaultSettings = {name: 'Default'};

console.log(userSettings || defaultSettings); // {name: "Kevin"}

Relational Operators

"< > <= >="

Conditional Operator

const cruiseFamilyCounts = 5
let cruiseIsFun = cruiseFamilyCounts > 2 ? true : false;
console.log(`Cruise is fun? ${cruiseIsFun}`)

Assignment Operators

var1 += 10;
var1 -= 10;
var1 /= 10;
var1 %= 10;
var1 <<= 1;       // shift bit to left
var1 >>= 1;       // shift bit to right

Operatro Precedence

Click here MDN

Loop

traditional loop

const myCruiseHistory = [
  {
    cruiseDate: "23-DEC-2017",
    cruiseLine: "NCL Escape",
    noOfDays: 7
  },
  {
    cruiseDate: "22-DEC-2018",
    cruiseLine: "NCL Bliss",
    noOfDays: 7
  },
  {
    cruiseDate: "22-DEC-2019",
    cruiseLine: "NCL Epic",
    noOfDays: 7
  }
];

// Traitional For loop
for (i = 0; i < myCruiseHistory.length; i++) {
  console.log(
    `I cruise on ${myCruiseHistory[i].cruiseDate} with ${myCruiseHistory[i].cruiseLine} for ${
      myCruiseHistory[i].noOfDays
    } days`
  );
}

// I cruise on 23-DEC-2017 with NCL Escape for 7 days
// I cruise on 22-DEC-2018 with NCL Bliss for 7 days
// I cruise on 22-DEC-2019 with NCL Epic for 7 days
// --------------------------------------------------------------

// Enhanced For loop
// Please notice keyword "of", it is not "in"
for (let cruise of myCruiseHistory) {
  console.log(`I cruise on ${cruise.cruiseDate} with ${cruise.cruiseLine} for ${cruise.noOfDays} days`);
}

// I cruise on 23-DEC-2017 with NCL Escape for 7 days
// I cruise on 22-DEC-2018 with NCL Bliss for 7 days
// I cruise on 22-DEC-2019 with NCL Epic for 7 days
// --
// --------------------------------------------------------------

// While loop
let idx = 0;

while (idx < myCruiseHistory.length) {
  console.log(
    `I cruise on ${myCruiseHistory[idx].cruiseDate} with ${myCruiseHistory[idx].cruiseLine} for ${
      myCruiseHistory[idx].noOfDays
    } days`
  );

  // don't forget increase index
  idx++;
}

// I cruise on 23-DEC-2017 with NCL Escape for 7 days
// I cruise on 22-DEC-2018 with NCL Bliss for 7 days
// I cruise on 22-DEC-2019 with NCL Epic for 7 days

high-order forEach loop

see Array section

Functions and Scope

Function Scope

// Example 1: nested functions ...
// message is defined in parent func and referred in child func
function startCruise(cruiseDate) {
  let message = `Starting cruise on date ${cruiseDate} ...`;

  let startFn = function packStuff() {
    console.log(message);
  };

  startFn();
}

startCruise("22-Dec-2018");    // Starting cruise on date 22-Dec-2018

// Example 2: child declare (using let) same variable as parent variable
// Because let has block scope. These 2 variables are independent
// from each other

function startCruise(cruiseDate) {
  let message = `Starting cruise on date ${cruiseDate} ...`;

  let startFn = function packStuff() {
    let message = `Cruise is cancelled due to bad weather`;
  };

  startFn();
  console.log(message);
}

startCruise("22-Dec-2018"); // Starting cruise on date 22-Dec-2018

Block Scope: scope between block, which is {}

// Example 1
let cruiseDays = 7;
if (cruiseDays === 7) {
  let message = "It is a 7 days cruise";
}

console.log(message);       // Error

// Example 2
let message = "a short cruise";

let cruiseDays = 7;
if (cruiseDays === 7) {
  let message = "7 days cruise";
  console.log(message); // It is a 7 days cruise
}

console.log(message); // a short cruise

// Example 3: var is not block scope. in below,
// inner message is overwriting parent's message variable
var message = 'Outside';

if (5 === 5) {
    var message = 'Equal';
    console.log(message);   // Equal
}

console.log(message);       // Equal

IIFE: Immediately Invoked Function Expression

IIFE is a pattern

This technique is very common in JavaScript libraries. It creates a closure around the entire contents of the file which creates a private namespace and thereby helps avoid potential name clashes between different JavaScript modules and libraries. The function is immediately invoked so that the namespace (library name) is assigned the return value of the function.

// Example 1 : pay attention to beginning parenthess (
(function() {
  console.log("I will go to a cruise soon");
})();

// Example 2
let app = (function() {
  let cruiseKids = 10;
  console.log(`${cruiseKids} kids will go cruise`);
  return { };
})();

console.log(app);     // {}

const myLibrary = (function() {
  var privateVariable = 2
  return {
    publicMethod: () => privateVariable
  }
})()
privateVariable // ReferenceError
myLibrary.publicMethod() // 2```

### Closure

A closure is a way to access and manipulate external variables from within a function.

```javascript
let app = (function() {
  let cruiseKids = 10;
  let getCruiseKids = function() {
    return cruiseKids;
  };

  return {
    getCruiseKids: getCruiseKids
  };
})();

console.log(app.getCruiseKids()); // 10

The this keyword

"this" refers to the context when invoking function call

// Example 1
let kevin = {
  name: "Kevin Zhang",
  getName: function() {
    return this.name;
  }
};

console.log(kevin.getName()); // Kevin Zhang

call and apply

The main purpose of these 2 functions is to change the value of "this", or change the context of the function call

Both can be called on functions, which they run in the context of the first argument.

- In **call** the subsequent arguments are passed in to the function as they are
- In **apply** expects the second argument to be an array that it **unpacks** as arguments for the called function.
// Example 1: call
let kevin = {
  name: "Kevin Zhang",
  getName: function() {
    return this.name;
  }
};

let john = { name: "John Doe" };

console.log(kevin.getName.call(john));  // John Doe

// Example 2: apply
let kevin = {
  name: "Kevin Zhang",
  getName: function(prefix, suffix) {
    return `${prefix} ${this.name}, ${suffix}`;
  }
};

let john = { name: "John Doe" };

console.log(kevin.getName.apply(john, ["Your Name:", "Cool"])); // Your Name: John Doe, Cool

bind

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

//Example 1
let kevin = {
  name: "Kevin Zhang",
  getName: function(prefix) {
    return `${prefix} ${this.name}`;
  }
};

let john = { name: "John Doe" };
let newFn = kevin.getName.bind(john, 'Hi');
console.log(newFn()); // Hi John Doe

Scope & Context

  • Scope is the biggest source of confusion regarding variables.
  • Context is biggest source of confusion regarding objects.

Arrow Function

// Example 1a: even no parameter, still need ()
// Also no need 'return' & {} if just one line code
let getCruiseDate = () => '22-Dec-2018';

console.log(getCruiseDate());   // 22-Dec-2018

// Example 1b: some developer prefer use _ over () when no parameter
// using _ in this case is just an convention
let getCruiseDate = _ => '22-Dec-2018';

console.log(getCruiseDate());   // 22-Dec-2018

// Example 2: no need () if only one parameter
// Also no need 'return' & {} if just one line code
let getCruiseDate = d => `cruise date is ${d}`;

console.log(getCruiseDate("22-Dec-2018")); // cruise date is 22-Dec-2018

// Example 3: need () if having 2 or more parameters
let getCruiseDate = (d, noOfFamilies) =>
  `cruise date is ${d} with ${noOfFamilies} families`;

console.log(getCruiseDate("22-Dec-2018", 5)); // cruise date is 22-Dec-2018 with 5 families

// Example 4: need {} & **return** if more than 1 line in the code block
let getCruiseDate = (d, noOfFamilies) => {
  const cruiseLine = 'NCL Bliss';
  return `cruise date is ${d} with ${noOfFamilies} families with ${cruiseLine}`;
};

console.log(getCruiseDate("22-Dec-2018", 5)); // cruise date is 22-Dec-2018 with 5 families with NCL Bliss
  • Arrow functions are anonymous and change the way this binds in functions.
  • Arrow functions DO NOT have their own "this" value.
    • "this" refers to the enclosing context that code is running
// Example 1a: classic function: this refers to object received the event
document.addEventListener("click", function() {
  console.log(this);    // #document
});

// Example 1b: using arrow function
document.addEventListener("click", () => console.log(this)); // Window { ... }

// Example 2a: classic function
var cruise = {
    noOfDays: 7,
    takeOff: function() {
        console.log(this);
    }
};

cruise.takeOff(); // {noOfDays: 7, takeOff: ƒ}

// Example 2b: arrow function
var cruise = {
  noOfDays: 7,
  takeOff: () => console.log(this)
};

cruise.takeOff(); // Window { ...}

// Example 3:
var cruise = {
  noOfDays: 7,
  takeOff: function() {
    return () => console.log(this.noOfDays);
  }
};

cruise.takeOff()(); // 7

Default Parameters

  • the default parameter must list last (right side) of parameter list
let goCruise = function(noOfFamilies, cruiseLine = "RCL") {
  console.log(`${noOfFamilies} families will go cruise with ${cruiseLine}`);
};

console.log(goCruise(5)); // 5 families will go cruise with RCL
console.log(goCruise(5, "NCL")); //5 families will go cruise with NCL

Objects and Arrays

Constructor Functions

  • is used initialized new object

  • as convention, the first letter is UPPERCASE for constructor function name

// Example 0: common mistake: missing new keyword
// because of this, the "this" will be global window object 
// in this case, which is not what we typically want
function Cruise() {
  console.log(this);
}

let myCruise2018 =  Cruise(); // forgot "new" keyword

// Example 1: make sure you are using **new** keyword
function Cruise() {}

let myCruise2018 = new Cruise();

// Example 2: this Keyward in constructor function
function Cruise(cruiseDate, cruiseLine) {
  this.cruiseDate = cruiseDate;
  this.cruiseLine = cruiseLine;
}

let myCruise2018 = new Cruise("22-Dec-2018", "NCL");

console.log(
  `I will take cruise on ${myCruise2018.cruiseDate} with cruise line ${
    myCruise2018.cruiseLine
  }`
); // I will take cruise on 22-Dec-2018 with cruise line NCL

// Example 3: constructor function including Method in it
// make sure you are using "this" in this.dateToCruise in countingDays() method
function Cruise(cruiseDate, cruiseLine) {
  this.dateToCruise = cruiseDate;
  this.cruiseLine = cruiseLine;

  this.countingDays = function() {
    const oneDay = 24 * 60 * 60 * 1000;
    const today = new Date();
    const startDate = new Date(this.dateToCruise);    // don't forget this
    const diffDays = Math.round(
      Math.abs((today.getTime() - startDate.getTime()) / oneDay)
    );

    console.log(`Cruise will start in ${diffDays} days`);
  };
}

let myCruise2019 = new Cruise("22-Dec-2019", "NCL");

myCruise2019.countingDays(); // Cruise will start in 31

Prototypes

  • All JavaScript objects inherit properties and methods from a prototype
  • The Object.prototype is on the top of the prototype inheritance chain
  • The JavaScript prototype property allows you to add new properties to object constructors
// Example 1
function Cruise(cruiseDate, cruiseLine) {
  this.dateToCruise = cruiseDate;
  this.cruiseLine = cruiseLine;
}

Cruise.prototype.countingDays = function() {
  const oneDay = 24 * 60 * 60 * 1000;
  const today = new Date();
  const startDate = new Date(this.dateToCruise); // don't forget this
  const diffDays = Math.round(
    Math.abs((today.getTime() - startDate.getTime()) / oneDay)
  );

  console.log(`Cruise will start in ${diffDays} days!`);
};

let myCruise2018 = new Cruise("22-Dec-2018", "NCL");

myCruise2018.countingDays(); // Cruise will start in 31 days!

Expanding Objects Using Prototypes

// Example 1
String.prototype.hello = function() {
  return `${this.toString()}: How are you?`;
};

console.log('Kevin'.hello()); // Kevin: How are you?

JSON: JavaSCript Object Notation

// Example 1: convert JS object to JSON
// Below is not JSON, it is JS Code, object literal
let cruise2018 = {
  cruiseDate: "22-DEC-2018",
  cruiseLine: "NCL Bliss",
  noOfDays: 7
};

// pay attention to quotations in the result
// {"cruiseDate":"22-DEC-2018","cruiseLine":"NCL Bliss","noOfDays":7}
console.log(JSON.stringify(cruise2018));

// Example 2: convert JS array to JSON
const myCruiseHistory = [
  {
    cruise2017: {
      cruiseDate: "23-DEC-2017",
      cruiseLine: "NCL Escape",
      noOfDays: 7
    }
  },
  {
    cruise2018: {
      cruiseDate: "22-DEC-2018",
      cruiseLine: "NCL Bliss",
      noOfDays: 7
    }
  }
];

console.log(JSON.stringify(myCruiseHistory));

// JSON also use [] for array
// [{"cruise2017":{"cruiseDate":"23-DEC-2017","cruiseLine":"NCL Escape","noOfDays":7}},{"cruise2018":{"cruiseDate":"22-DEC-2018","cruiseLine":"NCL Bliss","noOfDays":7}}]

// Example 3: Parsing JSON
// below is using back tick
let jsonIn = `
  [
    {"kidAge": 9},
    {"kidAge": 6}
  ]
`;

let kidAges = JSON.parse(jsonIn);
console.log(kidAges); // [{kidAge: 9}, {kidAge: 6}]
console.log(typeof kidAges);  // object

Array check if contains a element - includes()

const family = ['Kevin', 'Ying', 'Brandon', 'Elena'];

console.log(family.includes('Kevin')); // true
console.log(family.includes('kevin')); // false

Array Iteration - forEach()

// Example: high-order forEach function
const myCruiseHistory = [
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017" },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018" }
];

myCruiseHistory.forEach(cruise =>
  console.log(`I went cruise on ${cruise.cruiseDate}`)
);
// I went cruise on 22-DEC-2018
// I went cruise on 23-DEC-2017

myCruiseHistory.forEach((cruise, index) =>
  console.log(
    `My ${index + 1} cruise is on ${cruise.cruiseDate} with ${
      cruise.cruiseLine
    }`
  )
);
// My 1 cruise is on 23-DEC-2017 with NCL Escape
// My 2 cruise is on 22-DEC-2018 with NCL Bliss

Array filtering - filter()

// Example
const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008" },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015" },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016" },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017" },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018" },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019" }
];

const myBestCruise = myCruiseHistory.filter(
  cruise => cruise.cruiseLine === "RCL Independency of Seas"
);

// don't forget [0] in below given filter will return an array
// even if the array only has one object for this example
console.log(
  `My best cruise vacation is on ${myBestCruise[0].cruiseDate} with ${
    myBestCruise[0].cruiseLine
  } `
);
// My best cruise vacation is on 23-DEC-2016 with RCL Independency of Seas

const my2019Cruise = myCruiseHistory.filter(
  cruise => cruise.cruiseDate.split('-')[2] === '2019'
);

console.log(
  `My upcoming 2019 cruise vacation will be on ${my2019Cruise[0].cruiseDate} with ${
  my2019Cruise[0].cruiseLine
  } `
//My upcoming 2019 cruise vacation will be on 14-DEC-2019 with RCL Symphony
);

Array Transforming - map()

const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008" },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015" },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016" },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017" },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018" },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019" }
];

const myCruiseYears = myCruiseHistory.map(
  cruise => cruise.cruiseDate.split('-')[2]
);

console.log(
  `I have cruised in year: ${myCruiseYears}`
);
// I have cruised in year: 2008,2015,2016,2017,2018,2019

Array Testing - every(), some()

  • result is either true or false
// Example
const myCruiseHistory = [
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016", days: 5 },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 }
];

const allCruises5DaysMore = myCruiseHistory.every(cruise => cruise.days >= 5);
console.log(allCruises5DaysMore); // false

const allCruises4DaysMore = myCruiseHistory.every(cruise => cruise.days >= 4);
console.log(allCruises4DaysMore); // true

const myCruiseHistory = [
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  { cruiseLine: "RCL Ind of Seas", cruiseDate: "11-DEC-2016", days: 5 },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 }
];

const someCruise7Days = myCruiseHistory.some(cruise => cruise.days === 7);
console.log(someCruise7Days); // true

Array: locate the First Match: find()

  • returns the value of the first element in an array that pass a test
// Example
const myCruiseHistory = [
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  {
    cruiseLine: "RCL Independency of Seas",
    cruiseDate: "11-DEC-2016",
    days: 5
  },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 }
];

const first7DaysCruise = myCruiseHistory.find(cruise => cruise.days === 7);
console.log(
  `My 1st 7-days cruise is with ${first7DaysCruise.cruiseLine} on ${
    first7DaysCruise.cruiseDate
  }`
);a
// My 1st 7-days cruise is with NCL Escape on 23-DEC-2017

const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008" },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015" },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016" },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017" },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018" },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019" }
];

//  ES5 - indexOf
const myFirstRCLCruise = myCruiseHistory.find(
  cruise => cruise.cruiseLine.indexOf('RCL') >= 0
);

console.log(
  `My first cruise with RCL was: ${myFirstRCLCruise.cruiseDate} with ${
  myFirstRCLCruise.cruiseLine}`
);
//My first cruise with RCL was: 1-AUG-2008 with RCL Majesty

Array: reduce()

const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008", days: 3 },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016", days: 5 },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019", days: 7 }
];

// acc: accumulator
const myTotalCruiseDays = myCruiseHistory.reduce(
  (acc, cruise) => acc += cruise.days,
  0);

console.log(`So far I have cruised ${myTotalCruiseDays} days`);
// So far I have cruised 33 days

// v2: chaining map + reduce
const myTotalCruiseDays2 = myCruiseHistory.map(cruise => cruise.days).reduce(
  (acc, day) => acc += day,
  0);

console.log(`So far I have cruised ${myTotalCruiseDays2} days`);
// So far I have cruised 33 days
```# Modern JavaScript Cheat Sheet - Part A

Support\Web_Cloud\WEB_Javascript_A.md

## Constant

- Constant must be initialized and value can't be changed (for primitive type)
- By convention, constant variable shuold be **UPPERCASE**

```javascript

// Example 1
const CAR_ID = 42;
const BODY_STYLE;        // error! need initialization

CAR_ID = 100;            // error! can't change value

// Example 2: constant has block scope
const CRUISE_DAYS = 7;
if (CRUISE_DAYS > 5) {
    const CRUISE_DAYS = 30;
}
console.log(CRUISE_DAYS);   // 7

Array: Truncating Array

https://medium.com/better-programming/11-extremely-useful-javascript-tips-4484429a5655

const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008", days: 3 },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016", days: 5 },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019", days: 7 }
];

// first 2 cruises
myCruiseHistory.length = 2;

console.log(myCruiseHistory);
// [ { cruiseLine: 'RCL Majesty', cruiseDate: '1-AUG-2008', days: 3 },
//  { cruiseLine: 'DCL Dream', cruiseDate: '10-DEC-2015', days: 4 } ]

Let and Var

Please read this thread to understand

  • 'var' variables are ‘function scope.’ What does this mean? It means they are only available inside the function they’re created in, or if not created inside a function, they are ‘globally scoped.’
  • 'let' and 'const' variables are scoped to the block
    • what is the block? A block is a set of opening and closing curly brackets
// Example 1a: ES5 **hoisting (竖起)** for "var"
console.log(carId); // undefined (not an error);
var carId = 4;

// Example 1b: ES6 let
console.log(carId); // ReferenceError;
let carId = 4;

// Example 1c: ES6 let
let carId;
console.log(carId); // undefined

// Example 2
if (true) {
  var foo = 9;
}
console.log(foo); // 9

if (true) {
  let foo = 9;
}
console.log(foo); // error!

// Example 3a: let has block scope
let daysBeforeCruise = 10;
{
  let daysBeforeCruise = 5;
}
console.log(daysBeforeCruise); // 10

// Example 3b: let has block scope
{
  let daysBeforeCruise = 5;
}
console.log(daysBeforeCruise); // ReferenceError

// Example 3d:
function updateCruiseDate() {
  cruiseDate = "22-DEC-2018";
}

let cruiseDate = null;
updateCruiseDate();
console.log(cruiseDate); // 22-DEC-2018

// Example 3e:
let noCruiseDays = 7;

for (let noCruiseDays = 0; noCruiseDays < 100; noCruiseDays++) {}
console.log(noCruiseDays); // 7

// Example 4a: ES5 "var" has global scope
let updateFunc = [];
for (var i = 0; i < 2; i++) {
  updateFunc.push(function() {
    return i;
  });
}
console.log(updateFunc[0]); // f () {return i;}
console.log(updateFunc[0]()); // 2    ==> most likely, this is unexpected result

// Example 4b: ES6 "let" has block scope
let updateFunc = [];
for (let i = 0; i < 2; i++) {
  updateFunc.push(function() {
    return i;
  });
}
console.log(updateFunc[0]); // f () {return i;}
console.log(updateFunc[0]()); // 0  ==> most likely, this is expected result

Rest Parameters: ...theRest

It allows us to represent an indefinite number of arguments as an array

// Example 1
function sendCars1(...allCarIds) {
  allCarIds.forEach(id => console.log(id));
}

sendCars1(100, 200, 300); // 100 200 300

// Example 2: named parameter (day) + Rest Parameter
// In such case, Rest Parameter must be **LAST** in the list

function sendCars2(day, ...allCarIds) {
  allCarIds.forEach(id => console.log(id));
}

sendCars2('Monday', 100, 200, 300); // 100 200 300

// Example 3: there is another parameter (anotherDay)
// after Rest Parameter ==> this is **syntax error**

function sendCars3(day, ...allCarIds, anotherDay) {
  allCarIds.forEach(id => console.log(id));
}

sendCars3('Monday', 100, 200, 300); // Error!

Destructing

Destructuring is a JavaScript expression that makes it possible to unpack and assign values from arrays, or properties from objects, into distinct variables.

Destructuring Arrays [a,b] = arr

To destruct array, variables on left assignment need within []

below is just some common examples, please read this for more cases

// Example 1
let carIds = [1, 2, 5];
let [car1, car2, car3] = carIds;

console.log(car1, car2, car3); // 1 2 5

// Example 2a
let introduction = ["Hello", "I", "am", "Kevin"];
let [greeting, pronoun] = introduction;

console.log(greeting); //"Hello"
console.log(pronoun); //"I"

// Example 2b
let [greeting, pronoun] = ["Hello", "I", "am", "Sarah"];

console.log(greeting); //"Hello"
console.log(pronoun); //"I"

// Example 2c: skipping items in an Array
let [greeting, , ,name] = ["Hello", "I", "am", "Kevin"];

console.log(greeting); //"Hello"
console.log(name); //"Kevin"

// Example 3a
// Please notice: restFamilies is an array variable
let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];
let myFamily, restFamilies;
[myFamily, ...restFamilies] = cruiseFamilies;
console.log(myFamily, restFamilies); // Kevin ["Gang", "Eric", "Kong", "Song"]

// Example 3b: skip the first array element
// Please notice: restFamilies is an array variable
let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];
let restFamilies;
[, ...restFamilies] = cruiseFamilies;
console.log(restFamilies); // ["Gang", "Eric", "Kong", "Song"]

// Example 3c: skip the first and 2nd array element
// Please notice: restFamilies is an array variable
let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];
let restFamilies;
[, , ...restFamilies] = cruiseFamilies;
console.log(restFamilies); // ["Eric", "Kong", "Song"]

// Example 3d: skip the first, assign 2nd element to a variable and assign rest to an array variable
// Please notice: restFamilies is an array variable
let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];
let myFamily, myBestFriend, restFamilies;
[, myBestFriend, ...restFamilies] = cruiseFamilies;
console.log(myBestFriend, restFamilies); // Gang ["Eric", "Kong", "Song"]

// Example 4: Swapping Values using Destructuring Assignment
let a = 3;
let b = 6;

[a, b] = [b, a];

console.log(a); //6
console.log(b); //3

Destructing Objects: ({a,b} = obj)

To destruct object, variables on left assignment need within {}

below is just some common examples, please read this for more cases

// Example 1a: both variables (myBrand, myColor) are undefined
// because the variable **name doesn't match** to object's attribute.
// Basically, the variables in the object on the left hand side
// should have the same name as a property key in the object.
// If the names are different, we'll get undefined.
let car = { brand: "Acura-MDX", color: "black" };

let { myBrand, myColor } = car;
console.log(myBrand, myColor);  // undefined undefined

// Example 1b: variable names are matching to object attributes
//             this is expected result
let car = { brand: "Acura-MDX", color: "black" };

let { brand, color } = car;
console.log(brand, color);  // Acura-MDX black

// Example 1c: if we want to assign values of an object to a new
// variable instead of using name of the property, we will do below
// In below example, the values extracted are passed to the new
// variables myBrand and myColor
let car = { brand: "Acura-MDX", color: "black" };

let { brand: myBrand, color: myColor } = car;
console.log(myBrand, myColor); // Acura-MDX black

// Example 3a: Variables declared before being assigned
//             below 3rd line is syntax error because {}
//             is also used for code block. The compiler is
//             confused in this case. See 3b for soution
let car = { brand: "Acura-MDX", color: "black" };
let brand, color;
{ brand, color } = car;       // error!
console.log(brand, color);

// Example 3b: using () around the assignment statement is
// required syntax when using object literal destructuring
// assignment without a declaration.
let car = { brand: "Acura-MDX", color: "black" };
let brand, color;
({ brand, color } = car);
console.log(brand, color); // Acura-MDX black

// Example 4: address is an object within an object.
// pay attention how we extract street
let user = {
  name: "Kevin Zhang",
  age: 44,
  address: {
    street: "100 ABC Street",
    city: "Libertyville",
    state: "IL",
    zip: "60048"
  }
};

const { name, age, address: { city } } = user;

console.log(name, age, city); // Kevin Zhang 44 Libertyvillek

Destructing Misc

// Example: destruct string
let [firstLetter, lastLetter] = "AZ";
console.log(`first Letter: ${firstLetter} last Letter: ${lastLetter}`);
// first Letter: A last Letter: Z

Destructing Advanced

// Example 1a
let [low, high] = [,];
console.log(`low is ${low} and high is ${high}`);
// low is undefined and high is undefined

// Example 1b: destructing requires an iterate object.
// "undefined" is not iterable
let [low, high] = undefined; // Syntax error: TypeError: undefined is not iterable
console.log(`low is ${low} and high is ${high}`);

// Example 1c: destructing requires an iterate object.
// "null" is not iterable
let [low, high] = null; // Syntax error: TypeError: null is not iterable
console.log(`low is ${low} and high is ${high}`);

// Example 1d: there is a comma after "high". this is ok
let [low, high, ] = [10, 20];
console.log(`low is ${low} and high is ${high}`); // low is 10 and high is 20

// Example 2a: destructing in "for x of y" loop
for (let [a, b] of [[1, 2], [3, 4]]) {
  console.log(`a is ${a} b is ${b}`);
}
// a is 1 b is 2
// a is 3 b is 4

Spread Syntax: fun(...arr)

allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

Read more about Spread

// Example 1

function startCruise(f1, f2, f3, f4, f5) {
  console.log(f1, f2, f3, f4, f5);
}

let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];

startCruise(...cruiseFamilies); // Kevin Gang Eric Kong Song

// Example 2: using spread and rest together
function startCruise(f1, f2, ...restFamilies) {
  console.log(f1, f2, restFamilies);
}

let cruiseFamilies = ["Kevin", "Gang", "Eric", "Kong", "Song"];

startCruise(...cruiseFamilies); // Kevin Gang ["Eric", "Kong", "Song"]

// Example 3: creating new object by copying from existing one
const brandon = {age: 10, school: "Copeland"};

const elena = {...brandon};

elena.age = 7;

console.log(elena.age);     // 7
console.log(brandon.age);   // 10


let y2019_cruiseFamilies = [
  {"family_name": "Kevin", "family_size": 4, "cruise": "RCL" },
  {"family_name": "Eric", "family_size": 4, "cruise": "NCL" },
  {"family_name": "Gang", "family_size": 3, "cruise": "NCL" },
  {"family_name": "Wei", "family_size": 4, "cruise": "NCL" }
];

const y2019_indexed_cruiseFamilies = y2019_cruiseFamilies.reduce(
  (acc, family) => ({...acc, [family.family_name]: family}), {}
)

// result
{ Kevin: { family_name: 'Kevin', family_size: 4, cruise: 'RCL' },
  Eric: { family_name: 'Eric', family_size: 4, cruise: 'NCL' },
  Gang: { family_name: 'Gang', family_size: 3, cruise: 'NCL' },
  Wei: { family_name: 'Wei', family_size: 4, cruise: 'NCL' } }

Type and Type conversion

  • JS is Dynamically Typed Language
    • Types are associated with values not variables
    • The same variables can hold multiple types
    • We do not need to specify types
    • Most other langueage are statically typed (Java, C#, C++, PLSQL)
    • There are supersets of JS and addons to allow static typing (TypeScript, FlowJS)

typeof()

typeof 100; // number
typeof true; // boolean
typeof "Kevin"; // string
typeof function() {}; // function
typeof {}; // object
// null is an object in C; Javascript roots from C
typeof null; // object, this is a bug. google 'typeof null is object" to read more
typeof undefined; // undefined
typeof NaN; // number
typeof Symbol()  //symbol, new ES6

Common Type Conversions

What is the difference between parseInt() and Number()?

// convert to string
let age = 44;
age.toString(); // "44"
String(age); // "44"
String(4+5); // "9"

// convert string to integer
Number.parseInt("0100"); // 100
Number.parseInt("0200AB"); // 200
Number.parseInt("A0200AB"); // NaN => if can't convert to a number
Number.parseInt("123.45"); // 123

// convert string to number
Number.parseFloat("12.345"); // 12.345
Number.parseFloat("12.345").toFixed(); // 12
Number.parseFloat("12.345").toFixed(1); // 12.3

// convert Boolean to string
let age2 = 44;
age2 = String(true); // "true"
console.log(age2.length); // 4
console.log((true).toString()); // "true"

// convert Boolean to number
console.log(Number(true)); // 1
console.log(Number(false)); // 0

// convert null to number
console.log(Number(null)); // 0

// convert date to string
let todayStr = String(new Date());
console.log(todayStr); // "Sun Apr 28 2019 13:51:49 GMT-0500 (Central Daylight Time)"
console.log(todayStr.length);  // 57

// convert array to string
console.log(String([1,2,3,4])); // "1,2,3,4"
console.log(String([1,2,3,4])); // 7

Operator

Equality Operators

== vs === != vs !==

== do implicit type conversion and then compare value === compare both type and value

1 == true; // true
1 === true; // false

let id = 123;

id == "123"; // true
id === "123"; // false

id != "123"; // false
id !== "123"; // true

Unary Operators

  • ++var1 var1++
  • --var1 var1--
  • +var1 -var1
let age = 44;
console.log(age++); // 44
console.log(age); // 45

let cruiseFamilies = 5;
console.log(++cruiseFamilies); // 6
console.log(cruiseFamilies); // 6

Logical Operators

Operator meaning
&& AND
|| OR
! reverse
// Example 1a: this is very common case
let userSettings = null;
let defaultSettings = {name: 'Default'};

console.log(userSettings || defaultSettings); // {name: "Default"}

// Example 1b: this is very common case
let userSettings = {name: "Kevin"};
let defaultSettings = {name: 'Default'};

console.log(userSettings || defaultSettings); // {name: "Kevin"}

Relational Operators

"< > <= >="

Conditional Operator

const cruiseFamilyCounts = 5
let cruiseIsFun = cruiseFamilyCounts > 2 ? true : false;
console.log(`Cruise is fun? ${cruiseIsFun}`)

Assignment Operators

var1 += 10;
var1 -= 10;
var1 /= 10;
var1 %= 10;
var1 <<= 1;       // shift bit to left
var1 >>= 1;       // shift bit to right

Operatro Precedence

Click here MDN

Loop

traditional loop

const myCruiseHistory = [
  {
    cruiseDate: "23-DEC-2017",
    cruiseLine: "NCL Escape",
    noOfDays: 7
  },
  {
    cruiseDate: "22-DEC-2018",
    cruiseLine: "NCL Bliss",
    noOfDays: 7
  },
  {
    cruiseDate: "22-DEC-2019",
    cruiseLine: "NCL Epic",
    noOfDays: 7
  }
];

// Traitional For loop
for (i = 0; i < myCruiseHistory.length; i++) {
  console.log(
    `I cruise on ${myCruiseHistory[i].cruiseDate} with ${myCruiseHistory[i].cruiseLine} for ${
      myCruiseHistory[i].noOfDays
    } days`
  );
}

// I cruise on 23-DEC-2017 with NCL Escape for 7 days
// I cruise on 22-DEC-2018 with NCL Bliss for 7 days
// I cruise on 22-DEC-2019 with NCL Epic for 7 days
// --------------------------------------------------------------

// Enhanced For loop
// Please notice keyword "of", it is not "in"
for (let cruise of myCruiseHistory) {
  console.log(`I cruise on ${cruise.cruiseDate} with ${cruise.cruiseLine} for ${cruise.noOfDays} days`);
}

// I cruise on 23-DEC-2017 with NCL Escape for 7 days
// I cruise on 22-DEC-2018 with NCL Bliss for 7 days
// I cruise on 22-DEC-2019 with NCL Epic for 7 days
// --
// --------------------------------------------------------------

// While loop
let idx = 0;

while (idx < myCruiseHistory.length) {
  console.log(
    `I cruise on ${myCruiseHistory[idx].cruiseDate} with ${myCruiseHistory[idx].cruiseLine} for ${
      myCruiseHistory[idx].noOfDays
    } days`
  );

  // don't forget increase index
  idx++;
}

// I cruise on 23-DEC-2017 with NCL Escape for 7 days
// I cruise on 22-DEC-2018 with NCL Bliss for 7 days
// I cruise on 22-DEC-2019 with NCL Epic for 7 days

high-order forEach loop

see Array section

Functions and Scope

Function Scope

// Example 1: nested functions ...
// message is defined in parent func and referred in child func
function startCruise(cruiseDate) {
  let message = `Starting cruise on date ${cruiseDate} ...`;

  let startFn = function packStuff() {
    console.log(message);
  };

  startFn();
}

startCruise("22-Dec-2018");    // Starting cruise on date 22-Dec-2018

// Example 2: child declare (using let) same variable as parent variable
// Because let has block scope. These 2 variables are independent
// from each other

function startCruise(cruiseDate) {
  let message = `Starting cruise on date ${cruiseDate} ...`;

  let startFn = function packStuff() {
    let message = `Cruise is cancelled due to bad weather`;
  };

  startFn();
  console.log(message);
}

startCruise("22-Dec-2018"); // Starting cruise on date 22-Dec-2018

Block Scope: scope between block, which is {}

// Example 1
let cruiseDays = 7;
if (cruiseDays === 7) {
  let message = "It is a 7 days cruise";
}

console.log(message);       // Error

// Example 2
let message = "a short cruise";

let cruiseDays = 7;
if (cruiseDays === 7) {
  let message = "7 days cruise";
  console.log(message); // It is a 7 days cruise
}

console.log(message); // a short cruise

// Example 3: var is not block scope. in below,
// inner message is overwriting parent's message variable
var message = 'Outside';

if (5 === 5) {
    var message = 'Equal';
    console.log(message);   // Equal
}

console.log(message);       // Equal

IIFE: Immediately Invoked Function Expression

IIFE is a pattern

This technique is very common in JavaScript libraries. It creates a closure around the entire contents of the file which creates a private namespace and thereby helps avoid potential name clashes between different JavaScript modules and libraries. The function is immediately invoked so that the namespace (library name) is assigned the return value of the function.

// Example 1 : pay attention to beginning parenthess (
(function() {
  console.log("I will go to a cruise soon");
})();

// Example 2
let app = (function() {
  let cruiseKids = 10;
  console.log(`${cruiseKids} kids will go cruise`);
  return { };
})();

console.log(app);     // {}

const myLibrary = (function() {
  var privateVariable = 2
  return {
    publicMethod: () => privateVariable
  }
})()
privateVariable // ReferenceError
myLibrary.publicMethod() // 2```

### Closure

A closure is a way to access and manipulate external variables from within a function.

```javascript
let app = (function() {
  let cruiseKids = 10;
  let getCruiseKids = function() {
    return cruiseKids;
  };

  return {
    getCruiseKids: getCruiseKids
  };
})();

console.log(app.getCruiseKids()); // 10

The this keyword

"this" refers to the context when invoking function call

// Example 1
let kevin = {
  name: "Kevin Zhang",
  getName: function() {
    return this.name;
  }
};

console.log(kevin.getName()); // Kevin Zhang

call and apply

The main purpose of these 2 functions is to change the value of "this", or change the context of the function call

Both can be called on functions, which they run in the context of the first argument.

- In **call** the subsequent arguments are passed in to the function as they are
- In **apply** expects the second argument to be an array that it **unpacks** as arguments for the called function.
// Example 1: call
let kevin = {
  name: "Kevin Zhang",
  getName: function() {
    return this.name;
  }
};

let john = { name: "John Doe" };

console.log(kevin.getName.call(john));  // John Doe

// Example 2: apply
let kevin = {
  name: "Kevin Zhang",
  getName: function(prefix, suffix) {
    return `${prefix} ${this.name}, ${suffix}`;
  }
};

let john = { name: "John Doe" };

console.log(kevin.getName.apply(john, ["Your Name:", "Cool"])); // Your Name: John Doe, Cool

bind

The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.

//Example 1
let kevin = {
  name: "Kevin Zhang",
  getName: function(prefix) {
    return `${prefix} ${this.name}`;
  }
};

let john = { name: "John Doe" };
let newFn = kevin.getName.bind(john, 'Hi');
console.log(newFn()); // Hi John Doe

Scope & Context

  • Scope is the biggest source of confusion regarding variables.
  • Context is biggest source of confusion regarding objects.

Arrow Function

// Example 1a: even no parameter, still need ()
// Also no need 'return' & {} if just one line code
let getCruiseDate = () => '22-Dec-2018';

console.log(getCruiseDate());   // 22-Dec-2018

// Example 1b: some developer prefer use _ over () when no parameter
// using _ in this case is just an convention
let getCruiseDate = _ => '22-Dec-2018';

console.log(getCruiseDate());   // 22-Dec-2018

// Example 2: no need () if only one parameter
// Also no need 'return' & {} if just one line code
let getCruiseDate = d => `cruise date is ${d}`;

console.log(getCruiseDate("22-Dec-2018")); // cruise date is 22-Dec-2018

// Example 3: need () if having 2 or more parameters
let getCruiseDate = (d, noOfFamilies) =>
  `cruise date is ${d} with ${noOfFamilies} families`;

console.log(getCruiseDate("22-Dec-2018", 5)); // cruise date is 22-Dec-2018 with 5 families

// Example 4: need {} & **return** if more than 1 line in the code block
let getCruiseDate = (d, noOfFamilies) => {
  const cruiseLine = 'NCL Bliss';
  return `cruise date is ${d} with ${noOfFamilies} families with ${cruiseLine}`;
};

console.log(getCruiseDate("22-Dec-2018", 5)); // cruise date is 22-Dec-2018 with 5 families with NCL Bliss
  • Arrow functions are anonymous and change the way this binds in functions.
  • Arrow functions DO NOT have their own "this" value.
    • "this" refers to the enclosing context that code is running
// Example 1a: classic function: this refers to object received the event
document.addEventListener("click", function() {
  console.log(this);    // #document
});

// Example 1b: using arrow function
document.addEventListener("click", () => console.log(this)); // Window { ... }

// Example 2a: classic function
var cruise = {
    noOfDays: 7,
    takeOff: function() {
        console.log(this);
    }
};

cruise.takeOff(); // {noOfDays: 7, takeOff: ƒ}

// Example 2b: arrow function
var cruise = {
  noOfDays: 7,
  takeOff: () => console.log(this)
};

cruise.takeOff(); // Window { ...}

// Example 3:
var cruise = {
  noOfDays: 7,
  takeOff: function() {
    return () => console.log(this.noOfDays);
  }
};

cruise.takeOff()(); // 7

Default Parameters

  • the default parameter must list last (right side) of parameter list
let goCruise = function(noOfFamilies, cruiseLine = "RCL") {
  console.log(`${noOfFamilies} families will go cruise with ${cruiseLine}`);
};

console.log(goCruise(5)); // 5 families will go cruise with RCL
console.log(goCruise(5, "NCL")); //5 families will go cruise with NCL

Objects and Arrays

Constructor Functions

  • is used initialized new object

  • as convention, the first letter is UPPERCASE for constructor function name

// Example 0: common mistake: missing new keyword
// because of this, the "this" will be global window object 
// in this case, which is not what we typically want
function Cruise() {
  console.log(this);
}

let myCruise2018 =  Cruise(); // forgot "new" keyword

// Example 1: make sure you are using **new** keyword
function Cruise() {}

let myCruise2018 = new Cruise();

// Example 2: this Keyward in constructor function
function Cruise(cruiseDate, cruiseLine) {
  this.cruiseDate = cruiseDate;
  this.cruiseLine = cruiseLine;
}

let myCruise2018 = new Cruise("22-Dec-2018", "NCL");

console.log(
  `I will take cruise on ${myCruise2018.cruiseDate} with cruise line ${
    myCruise2018.cruiseLine
  }`
); // I will take cruise on 22-Dec-2018 with cruise line NCL

// Example 3: constructor function including Method in it
// make sure you are using "this" in this.dateToCruise in countingDays() method
function Cruise(cruiseDate, cruiseLine) {
  this.dateToCruise = cruiseDate;
  this.cruiseLine = cruiseLine;

  this.countingDays = function() {
    const oneDay = 24 * 60 * 60 * 1000;
    const today = new Date();
    const startDate = new Date(this.dateToCruise);    // don't forget this
    const diffDays = Math.round(
      Math.abs((today.getTime() - startDate.getTime()) / oneDay)
    );

    console.log(`Cruise will start in ${diffDays} days`);
  };
}

let myCruise2019 = new Cruise("22-Dec-2019", "NCL");

myCruise2019.countingDays(); // Cruise will start in 31

Prototypes

  • All JavaScript objects inherit properties and methods from a prototype
  • The Object.prototype is on the top of the prototype inheritance chain
  • The JavaScript prototype property allows you to add new properties to object constructors
// Example 1
function Cruise(cruiseDate, cruiseLine) {
  this.dateToCruise = cruiseDate;
  this.cruiseLine = cruiseLine;
}

Cruise.prototype.countingDays = function() {
  const oneDay = 24 * 60 * 60 * 1000;
  const today = new Date();
  const startDate = new Date(this.dateToCruise); // don't forget this
  const diffDays = Math.round(
    Math.abs((today.getTime() - startDate.getTime()) / oneDay)
  );

  console.log(`Cruise will start in ${diffDays} days!`);
};

let myCruise2018 = new Cruise("22-Dec-2018", "NCL");

myCruise2018.countingDays(); // Cruise will start in 31 days!

Expanding Objects Using Prototypes

// Example 1
String.prototype.hello = function() {
  return `${this.toString()}: How are you?`;
};

console.log('Kevin'.hello()); // Kevin: How are you?

JSON: JavaSCript Object Notation

// Example 1: convert JS object to JSON
// Below is not JSON, it is JS Code, object literal
let cruise2018 = {
  cruiseDate: "22-DEC-2018",
  cruiseLine: "NCL Bliss",
  noOfDays: 7
};

// pay attention to quotations in the result
// {"cruiseDate":"22-DEC-2018","cruiseLine":"NCL Bliss","noOfDays":7}
console.log(JSON.stringify(cruise2018));

// Example 2: convert JS array to JSON
const myCruiseHistory = [
  {
    cruise2017: {
      cruiseDate: "23-DEC-2017",
      cruiseLine: "NCL Escape",
      noOfDays: 7
    }
  },
  {
    cruise2018: {
      cruiseDate: "22-DEC-2018",
      cruiseLine: "NCL Bliss",
      noOfDays: 7
    }
  }
];

console.log(JSON.stringify(myCruiseHistory));

// JSON also use [] for array
// [{"cruise2017":{"cruiseDate":"23-DEC-2017","cruiseLine":"NCL Escape","noOfDays":7}},{"cruise2018":{"cruiseDate":"22-DEC-2018","cruiseLine":"NCL Bliss","noOfDays":7}}]

// Example 3: Parsing JSON
// below is using back tick
let jsonIn = `
  [
    {"kidAge": 9},
    {"kidAge": 6}
  ]
`;

let kidAges = JSON.parse(jsonIn);
console.log(kidAges); // [{kidAge: 9}, {kidAge: 6}]
console.log(typeof kidAges);  // object

Array check if contains a element - includes()

const family = ['Kevin', 'Ying', 'Brandon', 'Elena'];

console.log(family.includes('Kevin')); // true
console.log(family.includes('kevin')); // false

Array Iteration - forEach()

// Example: high-order forEach function
const myCruiseHistory = [
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017" },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018" }
];

myCruiseHistory.forEach(cruise =>
  console.log(`I went cruise on ${cruise.cruiseDate}`)
);
// I went cruise on 22-DEC-2018
// I went cruise on 23-DEC-2017

myCruiseHistory.forEach((cruise, index) =>
  console.log(
    `My ${index + 1} cruise is on ${cruise.cruiseDate} with ${
      cruise.cruiseLine
    }`
  )
);
// My 1 cruise is on 23-DEC-2017 with NCL Escape
// My 2 cruise is on 22-DEC-2018 with NCL Bliss

Array filtering - filter()

// Example
const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008" },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015" },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016" },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017" },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018" },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019" }
];

const myBestCruise = myCruiseHistory.filter(
  cruise => cruise.cruiseLine === "RCL Independency of Seas"
);

// don't forget [0] in below given filter will return an array
// even if the array only has one object for this example
console.log(
  `My best cruise vacation is on ${myBestCruise[0].cruiseDate} with ${
    myBestCruise[0].cruiseLine
  } `
);
// My best cruise vacation is on 23-DEC-2016 with RCL Independency of Seas

const my2019Cruise = myCruiseHistory.filter(
  cruise => cruise.cruiseDate.split('-')[2] === '2019'
);

console.log(
  `My upcoming 2019 cruise vacation will be on ${my2019Cruise[0].cruiseDate} with ${
  my2019Cruise[0].cruiseLine
  } `
//My upcoming 2019 cruise vacation will be on 14-DEC-2019 with RCL Symphony
);

Array Transforming - map()

const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008" },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015" },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016" },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017" },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018" },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019" }
];

const myCruiseYears = myCruiseHistory.map(
  cruise => cruise.cruiseDate.split('-')[2]
);

console.log(
  `I have cruised in year: ${myCruiseYears}`
);
// I have cruised in year: 2008,2015,2016,2017,2018,2019

Array Testing - every(), some()

  • result is either true or false
// Example
const myCruiseHistory = [
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016", days: 5 },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 }
];

const allCruises5DaysMore = myCruiseHistory.every(cruise => cruise.days >= 5);
console.log(allCruises5DaysMore); // false

const allCruises4DaysMore = myCruiseHistory.every(cruise => cruise.days >= 4);
console.log(allCruises4DaysMore); // true

const myCruiseHistory = [
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  { cruiseLine: "RCL Ind of Seas", cruiseDate: "11-DEC-2016", days: 5 },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 }
];

const someCruise7Days = myCruiseHistory.some(cruise => cruise.days === 7);
console.log(someCruise7Days); // true

Array: locate the First Match: find()

  • returns the value of the first element in an array that pass a test
// Example
const myCruiseHistory = [
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  {
    cruiseLine: "RCL Independency of Seas",
    cruiseDate: "11-DEC-2016",
    days: 5
  },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 }
];

const first7DaysCruise = myCruiseHistory.find(cruise => cruise.days === 7);
console.log(
  `My 1st 7-days cruise is with ${first7DaysCruise.cruiseLine} on ${
    first7DaysCruise.cruiseDate
  }`
);a
// My 1st 7-days cruise is with NCL Escape on 23-DEC-2017

const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008" },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015" },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016" },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017" },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018" },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019" }
];

//  ES5 - indexOf
const myFirstRCLCruise = myCruiseHistory.find(
  cruise => cruise.cruiseLine.indexOf('RCL') >= 0
);

console.log(
  `My first cruise with RCL was: ${myFirstRCLCruise.cruiseDate} with ${
  myFirstRCLCruise.cruiseLine}`
);
//My first cruise with RCL was: 1-AUG-2008 with RCL Majesty

Array: reduce()

const myCruiseHistory = [
  { cruiseLine: "RCL Majesty", cruiseDate: "1-AUG-2008", days: 3 },
  { cruiseLine: "DCL Dream", cruiseDate: "10-DEC-2015", days: 4 },
  { cruiseLine: "RCL Independency of Seas", cruiseDate: "11-DEC-2016", days: 5 },
  { cruiseLine: "NCL Escape", cruiseDate: "23-DEC-2017", days: 7 },
  { cruiseLine: "NCL Bliss", cruiseDate: "22-DEC-2018", days: 7 },
  { cruiseLine: "RCL Symphony", cruiseDate: "14-DEC-2019", days: 7 }
];

// acc: accumulator
const myTotalCruiseDays = myCruiseHistory.reduce(
  (acc, cruise) => acc += cruise.days,
  0);

console.log(`So far I have cruised ${myTotalCruiseDays} days`);
// So far I have cruised 33 days

// v2: chaining map + reduce
const myTotalCruiseDays2 = myCruiseHistory.map(cruise => cruise.days).reduce(
  (acc, day) => acc += day,
  0);

console.log(`So far I have cruised ${myTotalCruiseDays2} days`);
// So far I have cruised 33 days
@kzhangkzhang
Copy link
Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment