JavaScript basics

// html tags for JavaScript
<script>
</script>

Variables

Ending all lines with ; it's actually not required

Setting data into a variable, use either var, let, or const without setting var, let, or const the variable becomes GLOBAL local var takes precedent over global var

var varName = 1;

var can be used in the entire program let only in scope of where it was declared

const variable that can never change

A variables first letter should be lower case and camel case

console.log() lets us see in log console.log(varName);

Modulo exists %

++ and -- increment and decrement by 1; same as a += 1

+= -= *= /=  increment and decrement by  number you put after it

a += 12 is the same as a = a +12; a ++ 

use back tics to not have to use escape var string = `'my string with ' and "'`

use + to concatenate

+= to concatenate strings etc as well

Getting string length var len = varName.length

//// var vs let // let does not let you declare a variable twice // example of what's not allowed let varName = 0; let varName = 1; // example of what is allowed let varName = 0; varName = 1; // var will declare a variable globally or locally if within a function // let scope is limited to the block or expression it was declared in // const can't be reassigned, should name const variables in ALL CAPS // mainly use const and let About Bracket notation varName[num] // String are immutable var varName = 'B string'; varName[0] = "A"; // This will produce an error since string are immutable varName = 'A string'; // find last letter [varName.length - 1] // Boolean true, false // What is? \r carriage return \b backspace \f form feed

IMPORTANT A Note On Copying

In JavaScript, certain data structures such as arrays, objects, functions, and maps have what is known as reference values. When copying these data structures, simply assigning a new variable to an existing data structure will result in the new variable referencing the same data, rather than creating a new, independent copy. This is because these data structures have reference values, meaning that they are passed by reference rather than by value.

To create a true copy of an array or object, the spread operator (...) can be used. For arrays, the spread operator expands the elements of the original array into a new array. For objects, object spread or manually creating a new object with the properties from the original can be used to create a true copy.

It is important to keep this reference value behavior in mind when working with data in JavaScript, as it can impact the behavior of your code. This reference value behavior is sometimes referred to as "pass-by-reference."

Besides arrays and objects, other data structures that have reference values and are pass-by-reference include:

  • Functions
  • Maps
  • Sets

It's important to note that primitive data types such as numbers, strings, symbols, and booleans are pass-by-value and do not have reference values.

Functions

About Functions
// You can leave a function at any time
// Create a function
function myfun(arg1, arg2) {
// code goes here
console.log(arg1 + arg2);
// If function has no return, it will return "undefined"
}
myfun(1, 2);

//// Arrow functions, i.e. anonymous function, short method of created a function 
//// returns implicitly, i.e. does a return without needing to specify return
// Traditional function declaration
const add = function(a, b) {
  return a + b;
};

// Arrow function declaration
const add = (a, b) => {
  return a + b;
};

// Arrow function with implicit return
const add = (a, b) => a + b;

// Call the function
console.log(add(3, 4)); // Output: 7

// Another example
// Anon function
num => Number.isInteger(num) 

// written out traditional
const function anon(num) {
  return Number.isInteger(num);
}

//// Default parameters
const function myFun(arg1, arg2 = 1) {
  return arg1 + arg2;
}

// Some higher order functions require a callback/function return such as filter
$ cat js.js 
arr = [1, 2, 3, 4]
let num = 1;
console.log(arr.filter(num => Number.isInteger(num) != num %2));
console.log(arr.filter(Number.isInteger(num)));
$ node js.js 
[ 2, 4 ]
console.log(arr.filter(Number.isInteger(num)));
                ^
TypeError: true is not a function
    at Array.filter (<anonymous>)

Arrays, which in Pythonic terms are dictionaries

the term "array literal" is often used to refer specifically to this syntax. let arr = [1, 2, 3]; which is produces an array no different than any other array like one created like this 

 

// Array structure
var myArray = ["value", "value2", 1];
// Nested array, or multidimensional array
var nestArray = [["value1", "value2"], "value3"];

// Bracket notation to find specific index in array
var data = nestArray[1];
console.log(data)
$ value3

// You can modify array with bracket notation
// Double bracket notation to get indexes of nested array
nestArray[1] = "value4";
console.log(nestArray);
$ ["value1", "value2"], "value4"

// Append to array with .push()
nestArray.push(['another', 'array']);
console.log(nestArray)
$ [["value1", "value2"], "value4", ['another', 'array']]
// Remove last element from array with .pop()
// nestArray.pop() removes the last item from array
// Remove first element from array with .shift()
// Add element to beginning of array with .unshift()
var nArray = [1, 2]
nArray.unshift(3);
console.log(nArray)
$ [3, 1, 2]

//// Iterate through array
total = 0;
var myArray = [1, 2, 3, 4];
for (var i = 0; i < myArray.length; i++) {
  total += myArray[i];
}

// const immutable array values are mutable
const array = [1, 2, 3];
array[0] = 4;
console.log(array); // [4, 2, 3]
// Prevent data mutation
// Object.freeze(CONSTANT_VAR);

Queue data structure in JavaScript

A queue is a data science term for data structure which removes an element from the front and adds an element to the back
function queue(arr, item) {
  arr.pop();
  return arr.unshift(item);
}
arr = [1, 2, 3];
consol.log("Before: " + JSON.stringify("arr"));
consol.log(queue(arr, 4));
consol.log("After: " + JSON.stringify("arr"));
$ Before: [1, 2, 3];
$ 1
$ After: [2, 3, 4];

Strict Equality Operators and Switch

=== Strict equality operator does NOT do type conversion 3 is not equal to '3'
!== is also strict
// By omitting break it will go to the next statement
// Switch uses strict equality operator.
<script>
function sw(val) {
switch(val) {
case 1:  answer = "alpha";
break;
case 2:  answer = "beta";
break;
case 3:  answer = "gamma";
break;
default:
answer = 'not in';
break;
}
return answer
}
// Strict not if
function typeCheck(a, b) {
if (a !== b) {
 // if a is '1' and b is 1, will return true, they are not equal
 return 'a is not equal to be, checked without type conversion';
 }
// If statement example
}
function ifing(a, b) {
if (a > b) {
  return a;
 } else if (a = b) {
 return b;
 } else {
 return 'this string';
 }
}

// to return a boolean you don't need an if statement
function no_ifing(a, b) {
return (a < b);
}
</script>

Objects in Pythonic terms are dictionaries

// Properties are keys
<script>
var myObj = {
 "property" : 1,
 "property thing" : 2
};

//// Two ways to access properties in an object
// these can be mixed
// First dot notation
var prop1 = myObj.property;
// Bracket notation, which is required if the property has a space in it
var prop2 = myObj["property thing"];
//Reassignment 
myObj.property = 2;
myObj["property thing"] = 3;

// Adding a property
myObj.prop = 'num';
</script>

// Deleting a property
delete myObj.prop;

// Check if object has a property
myObj.hasownProperty("property") // returns boolean

while & for loops

// While loops
var myArray = [];
var count = 0;
while (count < 5) {
  myArray.push(count);
  count++;
}

// for loops
var myArray = [];
for (var i = 0, i < 5, i++) {
  ourArray.push(i);
}

// minus equal -=
var myArray = [];
for (var i = 0, i < 5, i-=2) {
  ourArray.push(i);
}

Generate random numbers and rounding

// The Math.random() static method returns a floating-point, pseudo-random number that's greater than or equal to 0 and less than 1, 
// The Math.floor() static method always rounds down and returns the largest integer less than or equal to a given number.
var num;
// Random number between 0 and .9999 repeating
num = Math.random()
// Random number rounded DOWN to whole number
num = Math.floor(Math.random() * 20);

Conditional/Ternary Operator Statement

// Format: 
// condition ? if-true : if-false
a === b ? var = 1 : var = 2;
// is nestable
condition ? if-true : condition ? if-true : if-false;
return num > 0 ? "positive" : num < 0 ? "negative" :  "zero";

Arrow Functions work well with Higher Order Functions taking functions as arguments

when one function takes another function as an argument, good time for an arrow function
//// This, is an anonymous arrow function
num => Number.isInteger(num)
// Which is the same as this
const function anon(num) {
  return Number.isInteger(num);
}
// Some functions like the filter function require a "callback" i.e. function as an argument for example
// The filter function
// Example 1
const squaredIntegers = arr.filter(num => Number.isInteger(num));
// Example 2
$ cat js.js 
arr = [1, 2, 3, 4]
let num = 1;
console.log(arr.filter(num => Number.isInteger(num) != num %2));
console.log(arr.filter(Number.isInteger(num)));
$ node js.js 
[ 2, 4 ]
/home/user/js.js:4
console.log(arr.filter(Number.isInteger(num)));
                ^
TypeError: true is not a function

Rest Operator

The rest operator in JavaScript allows you to represent an indefinite number of arguments as an array. It is represented by three dots (...), and is used in function parameters. 

For example, consider a function sum that takes in an indefinite number of arguments and returns the sum of all of them.

function sum(...numbers) {
  let total = 0;
  for (let num of numbers) {
    total += num;
  }
  return total;
}

Python Equivalent of the Rest Operator 

def sum(*args):
  total = 0
  for num in args:
    total += num
  return total

print(sum(1, 2, 3, 4, 5)) # Output: 15

Spread Operator, used on arrays

The spread operator in JavaScript allows you to spread the elements of an array or an object into a new array or object, respectively. It can be used in various contexts, including function arguments, array literals, object literals, and more.

Combining arrays into a new array:

const array1 = [1, 2, 3];
const array2 = [4, 5, 6];
const combinedArray = [...array1, ...array2];
console.log(combinedArray); // [1, 2, 3, 4, 5, 6]

Copying an array:

Why would we use a spread operatore to combine arrays, can't we just do?

const originalArray = [1, 2, 3]; const copiedArray = originalArray;

No, using const copiedArray = originalArray; will create a reference to the original array, not a copy of it. This means that if you modify the copied array, the original array will also be modified. To create a true copy of the array, you can use the spread operator as follows: const copiedArray = [...originalArray];.

const originalArray = [1, 2, 3];
const copiedArray = [...originalArray];
console.log(copiedArray); // [1, 2, 3]

Expanding an array-like object into a real array:

The value 3 is not included in the output because it is not an element of the arrayLike object, but rather a property of the object. The spread operator only spreads the enumerable properties of an object, and length is not enumerable. Therefore, when you spread arrayLike into a new array, only the enumerable properties (0, 1, and 2) are included in the new array.

const arrayLike = {0: 'a', 1: 'b', 2: 'c', length: 3};
const realArray = [...arrayLike];
console.log(realArray); // ['a', 'b', 'c']

Spreading values in an object literals to create a new object with certain properties:

const object1 = {a: 1, b: 2, c: 3};
const object2 = {d: 4, e: 5, f: 6};
const combinedObject = {...object1, ...object2};
console.log(combinedObject); // {a: 1, b: 2, c: 3, d: 4, e: 5, f: 6}

Destructuring arrays and objects:

const array = [1, 2, 3];
const [a, b, c] = array;
console.log(a, b, c); // 1 2 3

const object = {a: 1, b: 2, c: 3};
const {a, b, c} = object;
console.log(a, b, c); // 1 2 3