# 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

# STICKERS!!!

Tweet me @jamesqquick and include hashtag #LearnBuildTeach

By James Quick

# Defense Against the JavaScript Dark Arts

In the magical world of JavaScript, you have the power to do almost anything, but with great power comes great responsibility. Do you have the magical prowess to protect yourself from the darkest depths of JavaScript? In this talk, we discuss 5 spells that you can use protect yourself from the most common JavaScript pitfalls. Some of these are as easy as a swish and flick of the old magic wand thanks to modern JavaScript tooling, but the rest comes from establishing best practices and a new mindset. After this talk, you will walk away head high and wand at the ready!

• 153