Javascript

Javascript Guide on MDN

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide

Expressions and Operators

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators

ES6 Vs ES5

http://es6-features.org/#Constants

Handy code

// to execute code in the Web Browser Console
(function(){
"use strict";
/* Start of your code */

function greetMe(yourName) {
    alert('Hello ' + yourName);
}

greetMe('World');

/* End of your code */
})();

// type of operator
console.log(typeof alert);
console.log(typeof Object());

Structure

Variable Declarations

  • var global variable

  • let block-scoped local variables

  • const block-scoped read-only named constant

// multiple declarations on a line
let user = 'John', age = 25, message = 'Hello'

// constants
const PI = 3.14

if (true) {
    let y = 5;
}
console.log(y);  // ReferenceError: y is not defined


data = {a: "apples", b: "book"}

//element access
data['b']
// or
data.b

let keys = Object.keys(data)
let values = Object.values(data)


// Destructuring Assignment
// define a variable in the local scope named b, whose value is data[b]
let {b} = data

// Here's another interesting unpacking syntax
let [name, age] = ['Mika', 28];


//undefined, which is a keyword, and is testable
var input;
if (input === undefined) {
    //do something
}

//undefined is also Boolean false

if (!input){
    console.log("variable is not yet defined")
}
Variable and function Hoisting

Variables defined and declared at the bottom of the script are initially parsed before The exeuction of the script, so they can be used in a statement before their declaration.

Hoisted Varables are always undefined Hoister functions work Hoisted function expression (function object assigned to a variable) doesn’t

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Grammar_and_types#variable_hoisting

Datatypes

  • null

  • undefined

  • Boolean: literals true and false

  • String

  • Number: including integers and floats

  • BigInt: an integer with arbitrary precision

  • Symbol: A data type whose instances are unique and immutable.

  • Object

// Strings and formatted strings
let str = "Hello"
let str2 = 'Single quotes are ok too'
let phrase = `can embed another ${str}`

// string concat
let s = "my" + "string"

// one one type of numbers
let n1 = 10, n2 = 3.14
typeof n1
typeof n2

Datatype Conversions

Converting String to Numbers

  • parseFloat()

  • parseInt()

let secret = 3.14

let data = 'the secret is ' + secret
// or
data = `the secret is ${secret}`

// number to string conversion happens automtically

// parse a binary number
parseInt("1111",2)

// parse a hexa number
parseInt("FF",16)

literals

// array syntax
let myarray = ['alpha', 'beta', 'gamma']

// array literal with missing gaps
let myarray = ['a','b',,,'e','f']


let num = 0xFFFF; //65K in decimal

// object literals, nested
// object keys can be numbers
var car = { manyCars: {a: 'Saab', b: 'Jeep'}, 7: 'Mazda' };

console.log(car.manyCars.b); // Jeep
console.log(car[7]); // Mazda

// regexp literal
var re = /ab+c/;

Control Flow and Error Handling

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling

  • {} block statement

  • if else statetment

  • switch statement

  • break statement

  • throw statement

  • try .. catch statement and blocks

  • finally block

Comparison Operators

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#comparison_operators

Block Statement

A bunch of statements grouped in a block scope

// block statement - multiple statements in one block
{let a;let b; let c} //local scope


let x = 0

// while statement
while ( x < 10 ) {/* a bunch of statements */; x++}

if else Statement

// if, else

if (condition_1) {
statement_1;
} else if (condition_2) {
statement_2;
} else if (condition_n) {
statement_n;
} else {
statement_last;
}

Warning

object references that are not null are of course true, and may cause the following issue

var b = new Boolean(false);
if (b)         // this condition evaluates to true
if (b == true) // this condition evaluates to false

switch statement

Pretty much the java switch, dynamically typed of course

switch (fruittype) {
case 'Oranges':
    console.log('Oranges are $0.59 a pound.');
    break;
case 'Mangoes':
    console.log('Mangoes are $0.56 a pound.');
    break;
case 'Papayas':
    console.log('Mangoes and papayas are $2.79 a pound.');
    break;
default:
console.log(`Sorry, we are out of ${fruittype}.`);
}

throw statement

// Create an object type UserException
function UserException(message) {
this.message = message;
this.name = 'UserException';
}

// Make the exception convert to a pretty string when used as a string
// (e.g., by the error console)
UserException.prototype.toString = function() {
return `${this.name}: "${this.message}"`;
}

// Create an instance of the object type and throw it
throw new UserException('Value too high');

try catch finally structure

function f() {
try {
    console.log(0);
    throw 'bogus';
} catch(e) {
    console.log(1);
    return true;    // this return statement is suspended
                    // until finally block has completed
    console.log(2); // not reachable
} finally {
    console.log(3);
    return false;   // overwrites the previous "return"
    console.log(4); // not reachable
}
// "return false" is executed now
console.log(5);   // not reachable
}
console.log(f()); // 0, 1, 3, false

Looping and Interation

  • for statement

  • do .. while statement

  • while statement

  • labeled statement

  • break statement

  • continue statement

  • for .. in statement

  • for .. of statetment

The classical for statement

for (let step = 0; step < 5; step++) {
    // Runs 5 times, with values of step 0 through 4.
    console.log('Walking east one step');
}

do while statement

let i = 0;
do {
i += 1;
console.log(i);
} while (i < 5);

while statement

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

labeled and break and continue

let x = 0;
let z = 0;
labelCancelLoops: while (true) {
console.log('Outer loops: ' + x);
x += 1;
z = 1;
while (true) {
    console.log('Inner loops: ' + z);
    z += 1;
    if (z === 10 && x === 10) {
        break labelCancelLoops;
    } else if (z === 10) {
        break;
        }
    }
}

let i = 0;
let j = 10;
checkiandj:
while (i < 4) {
    console.log(i);
    i += 1;
    checkj:
    while (j > 4) {
        console.log(j);
        j -= 1;
        if ((j % 2) === 0) {
        continue checkj;
        }
        console.log(j + ' is odd.');
    }
    console.log('i = ' + i);
    console.log('j = ' + j);
}

for in statement

Iterates over Object Property Names.

Warning

do not use for in or for of or use with Arrays, because it is slower, and more buggy with Arrays. Use Array.forEach and Array.map instead

Works like Python for Objects, but working nothing like python for arrays.

let data = {a:'apples',b:'book',c:'cat'}

// the keys of an object, and not the values
for (item in data){
    console.log(`I eat ${data[item]}`)
}
}

for of statement

Warning

do not use for in or for of or use with Arrays, because it is slower, and more buggy with Arrays. Use Array.forEach and Array.map instead

// To iterate over object values

let data = {a:'apples',b:'book',c:'cat'}

for (item of Object.values(data)){
    console.log(`I eat ${item}`)
}

Functions

Predefined Javascript Functions

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#predefined_functions

Function Declarations

function square(number) {
    return number * number;
}

Function Expressions

Function expressions can optionally be anonymous

//Anonymous function, cannot be called recursively
const square = function(number) { return number * number }

// this is a named function expression, can be called recursively
const factorial = function fac(n) { return n < 2 ? 1 : n * fac(n - 1) }


// functional programming
function map(f, a) {
let result = []; // Create a new Array
let i; // Declare variable
for (i = 0; i != a.length; i++)
    result[i] = f(a[i]);
return result;
}
const f = function(x) {
return x * x * x;
}
let numbers = [0, 1, 2, 5, 10];
let cube = map(f,numbers);
console.log(cube);


// Javascript functions are almost as dynamic as python's
function create_function(flavor){
    if (flavor == 'square'){
        return function(num){
            return num * num
        }
    } else if (flavor == 'cube'){
        return function(num){
            return num * num * num
        }
    }
}
create_function('square')(10)

function scope and Nested Functions and Closures

a function defined in the global scope can access all variables defined in the global scope. A function defined inside another function can also access all variables defined in its parent function, and any other variables to which the parent function has access.

Closures

Local Variables defined within the scope and reach of inner functions may live longer than their enclosing functions as long as the inner functions are reachable.

function outside(x) {
    // for the function inside(), this will act as stateful object data
    let z = 0;
    function inside(y) {
        z += 1;
        return x + y + z;
    }
    return inside;
}

fn_inside = outside(3);

result = fn_inside(5);

console.log(result);

result = fn_inside(5);

console.log(result);

Dynamic Arguments

Javascript Functions can take arbitrary arguments in runtime, beyond (or short of) those orginally defined in the function signature.

The arguments array-like object gives access to runtime arguments passed to the function.

function concat_func(separator) {
var result = ''; // initialize list
var i;
// iterate through arguments
for (i = 1; i < arguments.length; i++) {
    result += arguments[i] + separator;
}
return result;
}

console.log(concat_func("~","alpha","beta","omega"))

Default Values of Function Parameters

JS function parameters are still positional, meaning the order matters, but convenient way theo pre-initialize a parameter, which is still positional.

Stressing on positional: I don’t see a way to make the above example work with a default setting for the separator parameter.

function do_greeting(name = "stranger"){
    console.log(`hello ${name}!`)
}

do_greeting()

Rest Parameters (…argv) and array unpacking

Here is a very nice code block that combines argv as an array, and a map() function native to Javascript Arrays.

Like in most languages, argv must be placed at the end of the function parameter list

// the ... in function parameters defines argv
function multiply_each(value, ...argv){
    return argv.map( x => x * value )
}

// the ... unpacks an array to pass them as argv
console.log(multiply_each(2, ...[1,2,3,4,5]))

Arrow Functions

An arrow function expression has a shorter syntax compared to function expressions,

and does not have its own this, arguments, super, or new.target. Arrow functions are always anonymous.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Functions#arrow_functions

let elements = [
    'Hydrogen',
    'Helium',
    'Lithium',
    'Beryllium'
]

// the extra parentheses are needed
let elements_detailed = elements.map( x => ({x: x.length}) )

console.log(elements_detailed)

// with function expressions, we need to keep a different reference to Person's 'this'
// in variable self before 'this' gets shadowed by growUp()'s 'this'
// not very elegant

function Person() {
    var self = this;
    self.age = 0;

    setInterval(function growUp() {
        self.age++;
    }, 1000); // increment age every second
}

// Reimplementing with Arrow Functions
// since they don't have their own this, they effectively inherit this from Person

function Person() {
    this.age = 0
    setInterval(() => this.age++ , 1000);
}

let p = new Person()

console.log(p.age)

Indexed Collections

Array objects and their lengths

// creating arrays with literals

let arx1 = new Array('alpha','beta','gamma')
let arx2 = Array('alpha','beta','gamma')
let arx3 = ['alpha','beta','gamma']

// this will expand the size of the array from 3 to 11
arx1[10] = 'omega'

// truncate or expand the array by directly setting the length (weird)
arx1.length = 2


// preallocated arrays
// if one argument that is an integer, init an array with given size

let arx4 = new Array(20)
let arx5 = Array(25)

Iterating over Arrays

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#iterating_over_arrays

Warning

do not use for in or for of or use with Arrays, because it is slower, and more buggy with Arrays. Use Array.forEach and Array.map instead

let arx = ['apples','oranges','bananas']

// map generates a new array of return values of the given arrow function
let mx = arx.map( cx => ({color:cx, size:cx.length}) )

// forEach without a return value
arx.forEach( item => console.log(item) )

Array methods

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#array_methods

Typed Arrays

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#typed_arrays

Keyed Collections

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Keyed_collections

  • Map

  • WeakMap

  • Set

  • WeakSet

// Map
let sayings = new Map();
sayings.set('dog', 'woof');
sayings.set('cat', 'meow');
sayings.set('elephant', 'toot');
sayings.size; // 3
sayings.get('dog'); // woof
sayings.get('fox'); // undefined
sayings.has('bird'); // false
sayings.delete('dog');
sayings.has('dog'); // false

for (let [key, value] of sayings) {
console.log(key + ' goes ' + value);
}
// "cat goes meow"
// "elephant goes toot"

sayings.clear();
sayings.size; // 0


// Set

let mySet = new Set();
mySet.add(1);
mySet.add('some text');
mySet.add('foo');

mySet.has(1); // true
mySet.delete('foo');
mySet.size; // 2

for (let item of mySet) console.log(item);

Objects

Creation and Definition of Objects

Creating with Object()

var myCar = new Object()

// properties set and access with the dot syntax
myCar.make = 'Ford'

// or set and access via the bracket syntax
myCar['model'] = 'Mustang'

myCar.year = 1969

// function expression can use "this" to refer to its container object
myCar.honk = function() {console.log(`${this.make}: beep beep`)}

myCar.honk()

Creating with Constructor Functions

Within a constructor function, Arrow functions make more sense over function expressions

function Person(name = 'mohamed',age = 35){
this.name = 'mohamed'
this.age = age

this.greet = () => `hello, my name is ${this.name}!`
}

let p = new Person()

p.name
p.greet()

Creating with Object Initializer Literal

let carx = {
    make: 'Ford',
    model: 'Mustang',
    year: 1969,
    honk: function() {console.log(`${this.make}: beep beep`)}
}

carx.honk()

Enumerate the properties of an object

for in:

This method traverses all enumerable properties of an object and its prototype chain.

Object.keys(o):

This method returns an array with all the own (not in the prototype chain) enumerable properties’ names (“keys”) of an object

Object.getOwnPropertyNames(o):

This method returns an array containing all own properties’ names (enumerable or not) of an object

Object Prototypes and inheritance

A simple example

function Person(name = 'mohamed', age = 35) {
    this.name = name, this.age = age
}

Person.prototype.introduce = function() {
    console.log(`hello, my name is ${this.name}, and I am ${this.age}`)
}

p1 = new Person()

p2 = new Person('Lina', 24)

// leaving a default argument for the first, and passing 30 to the second
p3 = new Person(...[, 30])
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Details_of_the_Object_Model/figure8.1.png
function Employee() {
    this.name = '';
    this.dept = 'general';

    this.work = function () {
        console.log(`getting stuff done at ${this.dept}`)
    }
}


Employee.prototype.introduce = function () {
    console.log(`hello, my name is ${this.name}, and I am ${this.dept}`)
}

function Manager() {
    Employee.call(this);
    this.reports = [];
}
Manager.prototype = Object.create(Employee.prototype);
Manager.prototype.constructor = Manager;

function WorkerBee() {
    Employee.call(this);
    this.projects = [];
}
WorkerBee.prototype = Object.create(Employee.prototype);
WorkerBee.prototype.constructor = WorkerBee;

function SalesPerson() {
    WorkerBee.call(this);
    this.dept = 'sales';
    this.quota = 100;
}
SalesPerson.prototype = Object.create(WorkerBee.prototype);
SalesPerson.prototype.constructor = SalesPerson;

function Engineer() {
    WorkerBee.call(this);
    this.dept = 'engineering';
    this.machine = '';
}
Engineer.prototype = Object.create(WorkerBee.prototype)
Engineer.prototype.constructor = Engineer;


let px = new Engineer()
px.name = 'Mohamed'

Expressions and Operators

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators

Promises

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

Iterators and generators

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Iterators_and_Generators

Node Linux Process

//variable args
let args = process.argv
console.log(args)

//discard the first two elements of the array
args = process.argv.slice(2) // discarding the exec and the script path

//the process object has losts of useful info about the OS process
console.log(process)