/JavascriptRecap

An Intro to JS syntax

Primary LanguageJavaScript

JavascriptRecap

The Fundamentals


Types, Operators and Values

// numbers 
7.43

// Very small/big numbers can be represented using exponents (e)
2.4e8 // same as 240000000

+ // addition
* // multiplication 
- // subtraction 
% // remainder or modulo

// Creful using these two
Infinity // + infinity 
-Infinity // - infinity 

NaN // not a number (confused)

// As long as the the quotes at the start and the end of the string match
// String can be represented in 3 ways
"I am  a string"
'This is another string'
`Me too, but I am special` // template literals, allow for value-embedding

`5+5 is ${5+5}` // code 
"5+5 is 10" // output 

// Unary operator 
typeof 4; // code
"number" // output 

typeof "S" // code
"string" // output 

Numeric Comparison:

3 < 2 // less than
false // output

1.01 > 1 // greater than
true 

Strings Comparison: Sanity Check

"z" > "a" // is "z" greater than "a"
true // output

Strings are ordered alphabetically. "a" being the 'smallest' to "z" the 'largest'.

"Z" > "a" // is capital "Z" greater than "a"?
false // output 

Well, with the exception of uppercase letters. They are always “less” than lowercase ones.
To visually see it from "largest" to "smallest":

z > y > x > w > v > ... b > a > Z > Y > X > ... > B > A

(...) The three dots here simply indicate an intentional omission of the letters but the pattern should be clear.

So, how will javascript compare longer strings (i.e words, sentences)?
Javascript goes over the string from left to right, comparing the unicodes (characters) one by one:

  • Compares first characters of both words, decides whether one is greater or they're both equal.
  • When both firsts are equal, goes on to compare the next two.
  • Repeat until the end.
  • If both strings end at the same length, then they are equal. Otherwise, the longer string is greater.

Other

>= // greatr than or equal to 
<= // less than or equal to 
!= // not equal to 

Note: There is only one value in JavaScript that is not equal to itself, and that is NaN.

console.log(NaN == NaN)
false // this is bc it's the result of nonsensical computation and that can be different every time.

Logical Operators

Applied to Boolean values.

  • and: &&
  • or: ||
  • not: !

! flips the value behind it.
!true // read: not true
false // output: produces false 

null and undefined are empty values and the difference can be ignored.

Automatic Conversion

Javascript tries to please everyone. There's a cost to that "openness".

12 * null // multiplication 
0 // output 

"51" - 1 // the string "51" minus 1
50 // outputs the number 50

"5" + 1 // string "5" plus 1
"51" // outputs the string "51"

"five" * 2 // string "five" times 2
NaN // output 'Not a Number'

This is just Javascript being Javascript. This is called type coercion. JS notices an operation and tries its "best" to satisfy the instructions by quietly converting the values.
In the first case, null becomes 0. In the second case, it recognizes "51" as a string but also realizes that - is an operator on numerics and 1 is also a numeric value. Whereas in the third case, the + operator is used for concatinating two strings together and "5" is already a string, so it makes sense to cast 1 as a string as well.

== tests whether both values are the same.
=== tests whether the type and content matches.
!== Will return true if they're not equal in type and/or content.

Bindings (Variables)

Binding or variable assignment can be used interchangeably. JS uses three keywords for binding (creating a new variable), let, var (short for "variable") and const (short for "constant").

let name = "Ahmeda"; // 'let' connects the string "Ahmeda" to the binding (variable) 'name'.

// multiple bindings at the same time
let lastName = "Cheick", hobby = "Playing Soccer"; 

// using const to assign an age binding 
const age = 25;

const is used to define a constant variable which points to its value for as long as it 'lives'. So probably setting age to 25 with const isn't a good idea if I plan on living longer!

Note: var is the way variables were declared prior to 2015 in Javascript and it does mostly the same things as let, except that it's visible outside of its defined scope.

Conditionals: if else statements

if keyword executes or skips a statement depending on the value of a Boolean expression.

if (age == 25) {
    console.log(`You are ${age} years old!`);
}

When the statement wrapped in braces () isn't true, the program skips. Adding an else keyword lets it know what to do in that case.

else {
    console.log(`You are not ${age}!`)
}

You can check whether multiple expressions are true by chaining else ifs.

if (expressionOne) {
    doSomething();
} else if (expressionTwo) {
    doSomethingElse();
} else if (expressionThree) {
    doAnotherThing();
} else (whenNothingWorks) {
    wellDoThisThen();
}

Note: Indentation in javascript is simply to enhance code readibility unlike Python which "breathes" it. You could write your program in a single line if you wanted to. Don't do it!
Since you insist:

if (expressionOne){doSomething();} else if(expressionTwo{
doSomethingElse();}else if (expressionThree){doAnotherThing();} else (whenNothingWorks{wellDoThisThen();}

For Loops:


A simple for loop:
for (let number = 0; number <= 6; number + 2) {
    console.log(number);
}

A for loop consists of three parts, the for keyword itself, the statement in parentheses and finally the body whithin the {} which contains the instructions of what to do at every iteration.
The statement (let number = 0; number <= 6; number +2) does three things seperated by two semicolons. It initializes the loop, checks if it must continue and how it must update.

switch | Act-07

Switch allows you to put a number of scenarios (case labels) and javascript will start executing at the label that corresponds to the value that switch was given, or defaults when no matching value was found.
Let's say, depending on your budget you want to go somewhere for a vacation.

let budget = parseInt(prompt("What's your budget"));

switch (true) {
    case budget < 100:
    console.log("Take a walk around the block.");
    break;

    case budget >= 1000:
    console.log("let's to the beach");
    break;

    case budget > 5000:
    console.log("Hello, Vegas!")

    default:
    console.log("Let's discuss your finances.");
    break;
    }

Note: Don't forget the break statement, or else it will execute code you don't want.

Objects & Arrays

Arryas:

Arrays (lists) in Javascript are declared using square brackets.

let someArray = [2,57,63,5];

Every element has an index, starting from 0 and can be retrieved this way someArray[0].
You can access its property using a dot . or brackets. someArray.length or someArray["length"] do the same thing.
Note: Properties that contain functions are called methods.

someArray.push(76); // adds the number 76 at the end of the array and reutrns the new length of the array

someArray.pop(); // removes the last element and returns it.
76 // output  

// the corresponding methods for adding and removing elements
// at the start of an array are called unshift and shift

someArray.shift(); // removes first element 2 and returns it

someArray.unshift(2); // adds the numb 2 at the start of the array.

Note: To search for a specific element in an array we use indexOf method. Going from the start to end of the array it will return the index of that element when found. Otherwise, it will return -1.
To search from end to start instead we use lastIndexOf. Also, they both take a second optional argument indicating where to start searching from.

console.log([1, 2, 3, 2, 1].indexOf(2));
 // → 1
 console.log([1, 2, 3, 2, 1].lastIndexOf(2));
 // → 3

 console.log([1, 2, 3, 2, 1].indexOf(2,2)) // notice how it starts searching only from index 2.
 // → 3

 console.log([0, 1, 2, 3, 4].slice(2, 4)); // slice method used to return an inner array based on a range of indices. The second number is exclusive
 // → [2, 3]

The concat method can be used to glue arrays together to create a new array.


Objects
Objects are a collection of properties seperated by commas.
let someObject = {
    "type": true,
    "day": "Sunday",
}

Properties whose names aren't valid variables need to be quoted.
You can assign new values using the = operator. someObject.date = "10/06/2019". If it already existed, it will replace its value.

delete someObject.type; // deletes the property 'type'

console.log("type" in someObject); //checks whether 'type' still exists
false // console output 

Object.keys(someObject); // return the properties (keys)
["day","date"] // output 

Object.values(someObject) // similarly this one return the values
["Sunday", "10/06/2019"] // output 

Object.entries(someObject) // returns each key-value pair as an array.

someObject.date // the key can also be used to access the value
"10/06/2019" // output 

Functions:

Functions in Javascript are objects and possess all its capabilities.

const makeSomeNoise() = function() {
    console.log("Honk Honk!");
};
makeSomeNoise();
"Honk Honk!" // console output 

They can take multiple parameters or no parameter at all. Its body which is contained in the braces {} gets executed every time the function is called.

const addNumbers = function (numb1, numb2, numb3) {
    console.log(numb1 + numb2 + numb3); 
};
addNumbers(1, 2, 3);
6 // console output

The values of those parameters are assigned by its caller. Then a return statement determines the final output of that function.

Note: Each binding (variable) in JS has a scope where it's 'visible'. Variables with global scopre are visible and can be used anywhere in the program. Variables created inside a function are only visible within that function, they are local variables. Unless declared using the var keyword, in that case they are gloabl. There are also degrees to locality and functions can be nested.

Function Declaration:

function addNUmbers(n1, n2) {
    return n1 + n2;
}

Note: Function declaration doesn't require a semicolon after the function and it works differently.

// logging out half a quote and a function
console.log("'Always remember that you are absolutely unique." + secondPart());

function secondPart() {
    return " Just like everyone else.' -Margaret Mead";
}

If you haven't noticed, we called the function secondPart() before we've even declared it. This is because function declarations are not part of the top-to-bottom execution you're used to. Those functions get moved to the top of their scope and can be used anywhere within tha scope.

Arrow Function

The arrow => comes after the parameters then followed by the function's body. You can remember it this way "This list of params => will produce the following".

const addNumbers = (n1, n2) => {
    return n1 + n2; 
};

// these two do the same thing. 
const squared = (x) => { return x * 2; };
const squared =  x  => x * 2; // you can omit the braces {} for a single expression in the body

// when an arrow function has no params
const saySomething = () => {
    console.log("It was over my head.");
};

Parameters

function addition(x1, x2) {
    return x1 + x2;
}

console.log(addition(2, 2, "It's a beautiful day!"));

Note: if you pass too many arguments, they will get ignored. However, when you pass too few arguements, they will get replaced with undifined.
The = operator is used as default in case an argument isn't passed.

function addition(x1, x2 = Infinity) {
    return x1 + x2;
}
console.log(addition(2));
Infinity // console output 

Callback Functions:

We pass a function as an argument to another function that might, at a later point in execution, call the passed-in function.

function uselessFunction (callMeBack()) {
    return callMeBack();
}

Back to Objects: this | Act-07

As you know well by now, methods are properties that hold function values. We call them this way someObject.method(). A variable called this automatically points at the object it was called on. Let's slowly build on this.

let dog = {};

dog.speak = function (speech) {
    console.log(`The dog says: ${speech}`);
}

dog.speak("I can speak now!");
"The dog says: I can talk now!" // output 

Nothing new there! But watch closely:

 function speak(speech) {
            console.log(`The ${this.type} says '${speech}'`);
        }

let dog1 = {
    type: "Chihuahua",
    speak
        };
let hungryDog = {
    type: "boxer",
    speak
        };

hungryDog.speak("I am hungry");

Think of this as an extra parameter which isn't passed explicitly! However, if you want to pass it, you use a function's call method which takes this as its first argument and the rest arguements passed to it as normal arguements.

speak.call(hungryDog, "Burp!");
"The boxer says 'Burp!'" // output 

Promises


Javascript relies a lot on asynchronous computations. A promise is a placeholder for a value that we don’t have now but will have later. Well there ar only two possible outcomes; we either make good on our promise and we get the data as a value or something unexpected happens in that case we get an error.

var promise1 = new Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve('foo');
            }, 3000);
        });

promise1.then(function (value) {
    console.log(value);
    // expected output: "foo"
});

console.log(promise1);

To create a promise we use the built-in Promise constructor, to which pass a function. This, executor function, has two parameters. resolve and reject. This code (copied from documentation) uses the promise by calling the built-in then method on the Promise.

Let's say you're pulling a JSON file of all the troops and you want to send orders to the first soldier (at index zero).

getJSON("data/troops.json", function(err, troops){
  getJSON(troops[0].location, function(err, locationInfo){
    sendOrder(locationInfo, function(err, status){
     /*Process status*/
}) })
});

This code is difficult to understand and adding new steps can be very painful. Also, some of these steps can be done in parallel. Let's say we want to set a plan in motion that require us to know which soldier we have at our disposal, the plan itsel, and the location where our plan will play out, we could write something like this.

        var troops, mapInfo, plan;

        d3.json("data/troops.json", function (err, data) {
            if (err) {
                processError(err);
                return;
            }
            troops = data;
            actionItemArrived();
        });
        d3.json("data/mapInfo.json", function (err, data) {
            if (err) {
                processError(err);
                return;
            }
            mapInfo = data;
            actionItemArrived();
        });

        d3.json("plan.json", function (err, data) {
            if (err) {
                processError(err);
                return;
            }
            plan = data;
            actionItemArrived();
        });

        function actionItemArrived() {
            if (troops != null && mapInfo != null && plan != null) {
                console.log("The plan is ready to be set in motion!");
            }
        }

        function processError(err) {
            alert("Error", err)
        }