The Javascript Language

Javascript is the mainstream language of the web browser. A solid understanding of the fundamentals and advanced features of this language is crucial for any front-end development.

Javascript belongs to a category of programming languages called ‘high-level'. They are interpreted by an interpreter on runtime instead of compiled into machine code in lower level languages such as c/c++. High-level languages trade off low level optimization for convenient syntax and abstractions.

Task 1

Fork the project then sign in.

Open Lab 5

In modern javascript we declare variables in two ways.

Comments in Javascript are written using \\ for single line and \* *\ for multiline. Mathematical operators such as =, +, -, *, /, % are supported.

Task 2

Edit index.js and create variables "radius" assign it the value 7 and a constant "pi" assigned the value 3.14 then calculate area and stored in a variable called "area".

index.js

let radius = 7;
const pi = 3.14;

let area = radius * radius * pi;

Javascript is a dynamically typed language, this means datatypes are not given in the declaration of a variable. Instead, the compiler infers the variable's data type from its given value.

Primitive Data Types include

Numbers

let num1 = 0.1341 // float
let num2 = 2344 // integer
let num3 = 1.2e+3 // 12000 scientific notation
let num4 = Infinity // really large number
let num5 = 0b1000111 // binary number
let num6 = 0xFFF // hexadecimal number
let num7 = 9007199254740991n //BigInteger

Strings

Can be written in three ways.

let str1 ="Hello World";
let str2 = 'Hello World';
let str3 = `
    hello 
    world
`;// template literal (backtick above tab key)

console.log(str1, str2, str3);

Single (') and double (") quotes more or less have the same effect. However, template literals (`) (Backtick, the key under Esc) have two advantages:

  1. They can be multiline, i.e. the string can continue on a new line.
  2. String Interpolation

String interpolation is simply printing the values of variables or expressions within a string.

Task 3

Execute the following and observe the output.

let name = "bob";
let age = 24;

console.log(typeof(name))//string
console.log(typeof(age))//number

console.log(`Hello my name is ${name}, I'm ${age} years old`);
//Hello my name is bob, I'm 24 years old.

console.log(`I was born in ${2020 - age}`)
//I was born in 1966

You would notice that the values of name and age are logged in the string. This can only be done with template literals (`).

Type Coercion

Due to javascript's dynamic typing, it performs something called type coercion. This is where the language converts the data type of a variable to resolve an expression. This is best understood by seeing it for yourself.

Task 4.1

index.js

console.log('1' == 1); //true
console.log(1 == true); //true
console.log("false" == false); // "false" is not false
console.log("false" == true); // "false" is not true either

if("false")
   console.log("Hello false!") //but "false" is true enough here

Task 4.2

index.js

console.log('1' === 1); //false
console.log(1 === true); //false
console.log("true" === true); //false


If Statements

If statements work just the same as in any other language.

Comparison operators include

Logical operators include

let grade = 67;

if( grade < 50){
   console.log('Failed');
}else{
   console.log('Passed');
}


While and for

Same goes for while and for loops.

let num =0;

while(num < 10){
  console.log(num);
  num++;
}

for(let i=0; i <10; i ++){
  console.log(i);
}

Task 4.3

Write some code to print the numbers 1 - 50. However when a number divisible by 3 is reached ‘fizz' must be printed instead, when a number is divisible by 5 print ‘buzz'. If the number is divisible by 3 and 5 print ‘fizzbuzz' instead.

Answer

for(let i=0; i< 50; i++){
  if(i %3 === 0 && i%5 === 0){ // is divisible by 3 and 5?
    console.log('fizzbuzz');
  }else if(i%3 === 0){ // ok it's not divisible by both how about just 3?
    console.log('fizz');
  }else if(i%5 === 0){ //no? what about just 5 then?
    console.log('buzz');
  }else{              //so its not divisible by 3 or 5 then
    console.log(i);
  }
}

Date and Math are some built in javascript objects which are used for fundamental date and mathematical operations.

Unix Timestamp

The unix timestamp is simply a 10 digit number which counts the number of seconds since Jan 1st 1970. It is used to uniquely identify any second of any date. Eg 1581289838 translates to 02/09/2020 @ 11:10pm (UTC).

let nowTimestamp = Date.now();//store the current Date

console.log(nowTimestamp);//unix timestamp in milliseconds 1581291269848

let now = new Date(nowTimestamp);//today's Date object 

//months go from 0 - 11
let date = new Date(2019, 11, 17, 3, 24, 0);//December 17, 2019 03:24:00
//printing the date

console.log(date.toLocaleDateString("en-US"));//12/17/2019
//1 is added to month because January is 0
console.log(` ${now.getDate()} - ${now.getMonth() + 1} - ${now.getFullYear()} `); // 9 - 2 - 2020 

//Calculate difference between two dates in milliseconds
let difference = now - date;
//convert milliseconds to days

let daysBetween = difference * 1.15741e-8;
console.log(daysBetween);//54.6740790437368

The following are some useful mathematical functions and properties which can be used instead of implementing your own version.

let root = Math.sqrt(9);// 3

let cubed  = Math.pow(2, 3);// 8

let roundDown = Math.floor(12.3453);// 12

let roundUp = Math.ceil(12.3453);// 13

let absolute = Math.abs(-34);// 34

let randNum = Math.random();// random number between 0 and 1

let pi = Math.pi;// pi in radians * 180 to convert to degrees

//generate a random Integer between a supplied range
function randInt(min, max){
  return Math.floor(Math.random() * (max - min + 1) + min);
}

Functions are written as follows.

function hello() {
  console.log("hello");
}


Notice that there is no return type for functions as javascript is dynamically typed.

Parameters and Returning a Value

Functions can take parameters and return values. However, if the expected parameters aren't passed to a function they will receive an undefined value.

function add(a, b){
   return a + b;//undefined + undefined = NaN
}

let ans = add(5, 1);
console.log(ans); //6

let ans2 = add();
console.log(ans2); //NaN

When a mathematical operation is performed on a non numerical value such as a string or undefined it will result in a NaN (Not a Number) value.

Default Parameters

You can provide fallback values in function definitions in case the function is called with insufficient parameters. These are called default parameters

function add(a, b=10){
      return a + b;
}

console.log(add(5,11)); // logs 16

console.log(add(2));// logs 12

Now when add is called with just one parameter, b will fallback to the value of 10.

First Class Functions

A programming language is said to have First-class functions when functions in that language are treated like any other variable. For example, in such a language, a function can be passed as an argument to other functions, can be returned by another function and can be assigned as a value to a variable.

As a result of this, we must be careful and avoid name clashes between variable names and function names as variables cannot be declared more than once.

let sum = 10

function sum(){ //duplicate declaration error
}

As they are treated as variables this means that they can be passed to functions and can be returned by other functions.

Callback Functions

Because functions in javascript are first-class, they can be passed to other functions. Several JS methods take functions as parameters. When a parameter of a function is also a function said to be a callback function.

Task 5

Execute the following and observe the output

function happyPrint(string){
 console.log("😀: "+string);
}

function sadPrint(string){
 console.log("😢: "+string);
}

//This high-order function adds 2 parameters and passes the answer to the callback
function add(a, b, callback){
   let ans = a + b;
   callback(ans);// call the callback and pass the answer to it
}

//call add passing the callbacks to it

add(5, 10, happyPrint);
add(11, 12, sadPrint);

setInterval() is a timing function whereby we can perform iteration but control the time interval between loops. It works by receiving a function and a number of milliseconds, the function would be called every time the specified number of milliseconds has passed.

Task 2

Execute the following and observe the output.

 //prints current date
function printDate(){
   console.log(Date().toLocaleTimeString());
}
      
setInterval(printDate, 1000);

If you need to run the function once after a delay, setTimeout() can be used instead. The function would be executed once after the specified time in milliseconds has passed.

Due to being dynamically typed js arrays can be heterogeneous, this means the elements of an array can be of different data types. Like in other languages array elements can be accessed via their indices which start at 0;

let arr = []//empty array
let arr2 = [1, 2, 3, 4, 5, 6, 7]//initialize with elements
let arr3 = [1, 12.9, "Hi", '🎈', ]// heterogeneous array

console.log(arr[0]);// 1
console.log(arr3[3]);//🎈

Arrays can be iterated using its index or by using a For of loop. The useful property length exists on all arrays which can be used to get the size of an array.

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];// 10 elements

for(let i=0; i< arr.length; i++){
  console.log(arr[i])
}

for (let item of arr){// for of loop
   console.log(item);
}

Array Methods

There are several methods on array which are available for your convenience. They help make writing complex behaviors easilier. Some popular array methods include.

Task 5.1

Run the following code and observe the console.

let arr = [ -5, 16, 33, 42, 103, 344];

console.log(arr.includes(-5));//true

arr.push(11);//adds item to the end

console.log(arr)//[ -5, 16, 33, 42, 103, 344, 11];

let lastItem == arr.pop();//removes last item

console.log(lastItem, arr);//11, [ -5, 16, 33, 42, 103, 344]

arr.unshift(22);//adds item to the front

console.log(arr);//[22, -5, 16, 33, 42, 103, 344]

let firstItem = arr.shift();//removes first item
console.log(firstItem, arr);//22, [-5, 16, 33, 42, 103, 344]

let reversed = arr.reverse();//creates a new array in reverse order 
console.log(reversed);//[344, 103, 42, 33, 16, -5]
console.log(arr.join('-'));//"-5-103-16-33-344-42" joins array with provided separator

Callback-Based Array Methods

Here are some popular array methods that take callbacks and apply them to the elements of the array in some way.

Task 5.2

Try the following code in the script tag of index.html and observe the output in the console tab.

let arr = [12, 33, 4, 5, -4, 8, 19, 25];
                
//map() creates a new array from the elements of one without changing the old one
function double(num){
  return num * 2;
}

let doubledArr = arr.map(double); 
console.log(doubledArr);

function isOdd(num){
  return element%2 !== 0; 
}
//Filter takes a test condition and returns only the element which 
//make the condition true
let odds = arr.filter(isOdd);
console.log(odds);

//Returns true or false if any of the elements of the array 
//meets a specified condition
function has5Factor(){
  return ele % 5 === 0;
}

let hasFiveFactor = arr.some(has5Factor);
console.log(hasFiveFactor);

function intCompare(a, b){
 return a - b;
}

//sort function must return either 0, +ve, -ve
let ascending = arr.sort(intCompare)
console.log(ascending);

Arrays are collections with integer indices but what if we wanted our indices to be more meaningful and descriptive? JS Object literals, (dictionaries or associative arrays as known in other languages) help us achieve just that.

We can also put objects in array and let our object contain array values. Objects are key value pairs which can be used to create a mapping from a set of keys to a set of values.

let person = {
  // key : value
  "name": "John",
  "age": 12
};

//we can print the values of a key in two ways
console.log(person["age"]);//Using an index
console.log(person.name);//referencing the key as a property

person["weight"] = 70;

person.marks = [67, 34, 55, 89];

let firstMark = person.marks[0];

//mixing array and objects
let people = [
  person,
  {
    name: "Jane",
    age: 23,
    marks: [51, 78, 99, 76]
  }
];

let johnClone = {};//empty object

//copying objects
Object.assign(johnClone, person);

console.log(johnClone);


console.log(people[0].marks[0]);//what is printed?

Task 6

Write some code to record the height, weight and name of a collection of people. Then create a function which receives this collection and calculates their average bmi.

Answer

//Create a constructor a functions which builds object for us
function createPerson(name, height, weight) {
  return { name: name, height: height, weight: weight };
}

function calcBMI(weight, height) {
  return weight / (height * height);
}

function avgBMI(people) {
  let sum = 0;
  for (let person of people) {
    //sum the bmi of each person
    sum += calcBMI(person.weight, person.height);
  }
  //calculate average
  return sum / people.length;
}

//create a collection of people
let people = [
  createPerson("Sally", 60, 2.5),
  createPerson("Ben", 81, 3),
  createPerson("Shelly", 50, 1.7)
];

console.log(avgBMI(people));

Congratulations on making it to the end feel free to use labs 1-3 for javascript reference when building out your web applications.

Exercise

//object literal
let bob = {
  fname: "bob",
  lname: "smith",
  age: 18,
  height: 6,
  transcript:[
    {
      course: 'INFO 1603',
      grades: [ 89, 34, 67 ]
    },
    {
      course: 'INFO 1601',
      grades: [ 89, 34, 67 ]
    }
  ]
};

let sally = {
  fname: "sally",
  lname: "smith",
  age: 18,
  height: 6,
  transcript:[
    {
      course: 'INFO 1601',
      grades: [ 100, 89, 79 ]
    }
  ]
};

let paul = {
  fname: "paul",
  lname: "smith",
  age: 18,
  height: 6,
  transcript:[
    {
      course: 'INFO 1600',
      grades: [ 89, 34, 67 ]
    }
  ]
};


const students = [bob, sally, paul];

Given the code above implement the following functions:

getAverateGrade(student, course)

Given a student object and a course code, return the average grade the student has for that course or return -1 if the course is not in the student's transcript.

getAssignmentMark(student, course, num)

Given a student object, course number and assignment number returns the grade of that assignment of the given course of the student. If the student did not do the course, return -1.

function averageAssessment(students, courseName, assignment)

Given an array of students, a course code and an assignment number. Return the average of all the students mark for that assignment of that course.

References & Additional Reading

JS Type Coercion

Math Object

JS Date

Javascript Data Types

Javascript Functions

JS Array Methods

JS Objects