# JAVASCRIPT  Dark Arts

## James Q Quick

DEVELOPER. SPEAKER. TEACHER.

@jamesqquick

# STICKERS!!!

Tweet me @jamesqquick and include hashtag #LearnBuildTeach

# Double Equals

``````//Double equals compares loose equality using coercion
1 == '1' //true
false == 0 //true
false == '0' //true
0 == "" // true
"" == false //true
null == undefined //true
``````

# "Falsy Values"

``````//false
//0
//"",
//null
//undefined
//NAN``````

# "Falsy Values"

``````function printName(name){
if(!name){
console.log("YOU AINT GOT NO NAME!!");
}
else {
console.log(name);
}
}

printName() //YOU AINT GOT NO NAME!!
printName("James") //James``````

# Triple Equals

``````//Triple equals compares strong equality
//by comparing both type and value without coercion

1 === 1 //true
'Dark Arts' === 'Dark Arts' //true
true === true
1 === '1' //false
false === 0 //false
false === '0' //false
0 === "" // false
"" === false //false
``````

# Pass by Value

``````//Primitives are passed by value
//Primitives - undefined, null, boolean, string, number
let name = "James Quick";
const name2 = name;

console.log(name == name2); //true
console.log(name === name2); //true

name = "Jessica Quick";
console.log(name == name2); //false
console.log(name === name2); //false``````

# Pass by Value (cont.)

name =

"James Quick"

name2 =

"James Quick"

``````let name = "James Quick";
const name2 = name;

console.log(name == name2); //true
console.log(name === name2); //true

name = "Jessica Quick";
console.log(name == name2); //false
console.log(name === name2); //false``````

# Pass by Value (cont.)

name =

"Jessica Quick"

name2 =

"James Quick"

``````let name = "James Quick";
const name2 = name;

console.log(name == name2); //true
console.log(name === name2); //true

name = "Jessica Quick";
console.log(name == name2); //false
console.log(name === name2); //false``````

# Pass By Reference

``````//Objects are passed by reference
const p1 = {
first: 'James',
last: 'Quick',
}

let p2 = p1;
console.log(p2 === p1); //true

p1.first = "Jessica";
console.log(p2.first) //"Jessica"

p2 = { ...p1 };
console.log(p2 === p1); //false
``````

# Pass by Reference (cont.)

p1 =

p2 =

{

first: 'James',

last: 'Quick'

}

``````const p1 = {
first: 'James',
last: 'Quick',
}

let p2 = p1;
console.log(p2 === p1); //true

p1.first = "Jessica";
console.log(p2.first) //"Jessica"

p2 = { ...p1 };
console.log(p2 === p1); //false
``````

# Pass by Reference (cont.)

p1 =

p2 =

{

first: 'Jessica',

last: 'Quick'

}

``````const p1 = {
first: 'James',
last: 'Quick',
}

let p2 = p1;
console.log(p2 === p1); //true

p1.first = "Jessica";
console.log(p2.first) //"Jessica"

p2 = { ...p1 };
console.log(p2 === p1); //false
``````

# Pass by Reference (cont.)

p1 =

{

first: 'Jessica',

last: 'Quick'

}

``````const p1 = {
first: 'James',
last: 'Quick',
}

let p2 = p1;
console.log(p2 === p1); //true

p1.first = "Jessica";
console.log(p2.first) //"Jessica"

p2 = { ...p1 };
console.log(p2 === p1); //false
``````

p2 =

{

first: 'Jessica',

last: 'Quick'

}

# Default Parameters

``````const add = (num1, num2) => {
return num1 + num2;
}

# Default Parameters ES5

``````const add = (num1, num2) => {
if (num1 === undefined) {
num1 = 0;
}
if (num2 === undefined) {
num2 = 0;
}
return num1 + num2;
}

# Default Parameters ES5

``````const add = (num1, num2) => {
num1 = num1 || 0;
num2 = num2 || 0;
return num1 + num2;
}

# Default Parameters ES6

``````const add = (num1 = 0, num2 = 0) => {
return num1 + num2;
}

# Default Parameters ES5 Again

``````const addFromObject = (obj) => {
return obj.num1 + obj.num2;
}

# Default Parameters ES6 Again

``````const addFromObject = ({ num1 = 0, num2 = 0 } = {}) => {
return num1 + num2;
}

# Default Parameters Error Function

``````
function requiredArg() {
throw new Error('The argument is required');
}
function add(x = requiredArg(), y = requiredArg()) {
return x + y;
}

# Template Literal Strings

``````let markup = "<html>\n\t<head>\n\t</head>\n\t<body>\n\t</body>\n</html>"

markup =
`<html>
<body>
</body>
<html>`;

``````

# Template Literal Strings

``````const printPerson = (person) => {
console.log(person.first + " " + person.last + " lives in " + person.city + "." );

console.log(`\${person.first} \${person.last} lives in \${person.city}.`);
}
printPerson({first: "James", last: "Quick", city: "Memphis"});
``````

``````//Make shallow copies of arrays with the spread operator

const arr1 = [1, 2, 3, 4];
const arr2 = arr1;

arr1[0] = 15;
console.log(arr2[0]); //15

console.log(arr1 == arr2); //true

const arr3 = [...arr1];
console.log(arr3 == arr1); //false``````

``````//Make shallow copies of objects with the spread operator

const p1 = {
first: 'James',
last: 'Quick',
};

let p2 = p1;
console.log(p2 === p1); //true

p2 = { ...p1 };
console.log(p2 === p1); //false
``````

# JSON.parse(JSON.stringify(obj))

## Other ES6 Features

• Arrow Functions
• Promises
• Enhanced Object Literals
• Rest Operator
• Const and Let variables

# Callbacks

``````//Run code after a delay
setTimeout(() => {
console.log("1 second");
}, 1000);

//Add click event handler for a button
console.log("Button was clicked");
});``````

# Callback Hell

``````setTimeout(() => {
console.log("5");
setTimeout(() => {
console.log("4");
setTimeout(() => {
console.log("3");
setTimeout(() => {
console.log("2");
setTimeout(() => {
console.log("1");
}, 1000)
}, 1000)
}, 1000)
}, 1000)
}, 1000)

//5...4...3...2..1``````

# Promises

``````const axios = require('axios');

const url = "http://api.icndb.com/jokes/random?firstName=James&lastName=Quick"
axios.get(url)
.then( res => {
console.log(res.data.value.joke);
//"Product Owners never ask James Quick for more features. They ask for mercy."
})
.catch( err => {
console.log(err);
});
``````

# Promise Chaining

``````const todoURL = "https://jsonplaceholder.typicode.com/todos/1";
const userURL = "https://jsonplaceholder.typicode.com/users/"

axios.get(todoURL)
.then((res) => {
console.log(res.data); //userId = 1
return axios.get(userURL + res.data.userId);
})
.then(res => {
console.log(res.data) //user object
})
.catch(err => {
console.log("ERROR! " + err);
})``````

# Async/Await

``````const getJokeAsync = async () => {
const url = "http://api.icndb.com/jokes/random?firstName=James&lastName=Quick"
const res = await axios.get(url);
console.log(res.data.value.joke);
}

getJokeAsync();``````

# Async/Await

``````const getUserFromTodoAsync = async (todoId) => {
const todoURL = "https://jsonplaceholder.typicode.com/todos/" + todoId;
const userURL = "https://jsonplaceholder.typicode.com/users/"

const res = await axios.get(todoUrl);
const userRes = await axios.get(userURL + res.data.userId);
}``````

# Async/Await and Try/Catch

``````const getTodoAsync = async () => {
const todoURL = "https://jsonplaceholder.typicode.com/todos/1";
const userURL = "https://jsonplaceholder.typicode.com/users/"

try {
const res = await axios.get(todoUrl);
const userRes = await axios.get(userURL + res.data.userId);
} catch (ex) {
console.log("ERROR!" + ex);
}
}

getTodoAsync();
``````

# What is LINTING?

## Linting Benefits

• Consistent Code Formatting
• NO const reassignment and no undeclared variables
• Better timing/performance with Asynchronous JS
• No console.log()

# Formatting Before and After

``````const name = "James";

const person = { first: name,last:"Quick"}

function printPersonName(p){
console.log(p.first, p.last);
}

...

const name = 'James';

const person = { first: name, last: 'Quick' };

function printPersonName(p) {
console.log(p.first, p.last);
}

``````

# Write BETTER code FASTER

## Linting Setup

• Install eslint package to project
• Use `eslint --init` command
• follow prompts to create eslint configuration (creates .eslintrc file)
• Install eslint extension for VS Code
• Go into settings and check "Eslint: Auto Fix on Save"

# Linting JavaScript

``````npm init
npm install --save eslint
eslint --init
``````

# ESLint Configuration File

``````{
"env": {
"browser": true,
"commonjs": true,
"es6": true
},
"extends": "eslint:recommended",
"globals": {
},
"parserOptions": {
"ecmaVersion": 2018
},
"rules": {
"indent": [
"error",
"tab"
],
"linebreak-style": [
"error",
"unix"
],
"quotes": [
"error",
"single"
],
"semi": [
"error",
"always"
]
}
}``````

# The benefits...

## Benefits of TypeScript

• Optional static typings
• Converts to JavaScript
• Easily define object definitions with Interfaces
• Documentation and Intellisense

# Static Bindings - 1

``````function ICanAdd( num1, num2) {
return num1 + num2;
}

# Static Bindings - 2

``````function ICanAdd(num1: number, num2: number) {
return num1 + num2;
}

# Static Bindings - 3

``````function ICanAdd(num1: number, num2: number):number {
return num1 + num2;
}

``````

# Static Bindings - 4

``````
function ICanAdd(num1: number, num2: number):number {
return num1 + num2;
}

const num = ICanAdd(1, 2); //type of number is optional since function returns a number``````

# Static Bindings - 5

``````
function ICanAdd(num1: number, num2: number):number {
return num1 + num2;
}

num = "James" //YOU CAN"T DO THIS: num is of type number``````

## Compilation -Before/After

``````const message: string = 'hello world';

const first = 'James';

const person = { first, last: 'Quick', age: 28 };

const { last, age } = person;

console.log(`\${first} \${last} is \${age} years old!`);``````
``````var message = 'hello world';
var first = 'James';
var person = { first: first, last: 'Quick', age: 28 };
var last = person.last, age = person.age;
console.log(first + " " + last + " is " + age + " years old!");
``````

# Interfaces/Models

``````interface Person  {
first: string,
last: string,
age:number,
children: [],
spouse:Person
}``````

# Documentation

## Setup TypeScript

• Install TypeScript via NPMx
• Use tsc command followed by TypeScript file
• Create TypeScript configuration file
• Install TSLint extension VS Code

# TypeScript Config

``````{
"compilerOptions": {
/* Basic Options */
// "incremental": true,                   /* Enable incremental compilation */
"target": "es5",                          /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */
"module": "commonjs",                     /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */
// "lib": [],                             /* Specify library files to be included in the compilation. */
// "allowJs": true,                       /* Allow javascript files to be compiled. */
// "jsx": "preserve",                     /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */
// "declaration": true,                   /* Generates corresponding '.d.ts' file. */
// "declarationMap": true,                /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true,                     /* Generates corresponding '.map' file. */
// "outFile": "./",                       /* Concatenate and emit output to single file. */
// "outDir": "./",                        /* Redirect output structure to the directory. */
// "rootDir": "./",                       /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true,                     /* Enable project compilation */
// "tsBuildInfoFile": "./",               /* Specify file to store incremental compilation information */
// "noEmit": true,                        /* Do not emit outputs. */
// "importHelpers": true,                 /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true,            /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true,               /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */

/* Strict Type-Checking Options */
"strict": true,                           /* Enable all strict type-checking options. */
// "noImplicitAny": true,                 /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true,              /* Enable strict null checks. */
// "strictFunctionTypes": true,           /* Enable strict checking of function types. */
// "strictBindCallApply": true,           /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true,  /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true,                /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true,                  /* Parse in strict mode and emit "use strict" for each source file. */

// "noImplicitReturns": true,             /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true,    /* Report errors for fallthrough cases in switch statement. */

/* Module Resolution Options */
// "moduleResolution": "node",            /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./",                       /* Base directory to resolve non-absolute module names. */
// "paths": {},                           /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [],                        /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [],                       /* List of folders to include type definitions from. */
// "types": [],                           /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true,  /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true                   /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true,              /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true,          /* Allow accessing UMD globals from modules. */

/* Source Map Options */
// "sourceRoot": "",                      /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "",                         /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true,               /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true,                 /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */

/* Experimental Options */
// "experimentalDecorators": true,        /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true,         /* Enables experimental support for emitting type metadata for decorators. */
}
}
``````

# Learn VS Code

Coupon Code - KCDC2019