Skip to content

M03 - JavaScript - part 2

Object

JavaScript object is a collection of properties.

1
let person = {name: 'Arska', age: 49}

You can access object properies using . (dot) and/or [] chars.

1
2
console.log(person.name);   // Arska <- BETTER use dot notation!
console.log(person['age']); // 49 

You can add more properties later to your object.

1
2
person.id = "123345-1212";
console.log(person.id); // 123345-1212

Object Oriented Programming

  • You can use a functions inside your object, then they are called methods
  • Method can access properties using this keyword
  • Developer can use JavaScript build-in objects like Math, Date, String, Array and Object
  • Also HTML objects are available window, document, form, etc...
  • Developer can create his/her own objects
  • Developer can't use keywords like public, protected, private which are common in real OOP languages
  • Developer need to use new keyword to reserve memory for object
  • Function is used to define own class with properties and methods (ES5)
  • Developer will use constructor keyword in ES6

Example: OOP with function

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function Car(model) {
  // public property
  this.model  = model;
  // private variable (available only inside Car scope)
  let color = "Red";
  // public setter and getter methods with anonymous functions
  this.getColor = function() {
    return color;
  }
  this.setColor = function(newColor) {
   color = newColor;
  }
}

// create a new car instance
var car = new Car("Ford");
console.log(car.model); // Ford
console.log(car.getColor()); // Red
car.setColor("Blue");
console.log(car.getColor()); // Blue

// test access to private variable
console.log(car.color); // undefined

// test access to car color with global scope
console.log(color); // color is not defined

Prototype

Developer can add more properties or methods to object when app is running and instance has been created already.

1
2
3
car.speed = 165;
car.getSpeed = function(){return this.speed;};
console.log(car.getSpeed()); // 165

Developer can use prototype to add more properties and methods to all object instances.

1
2
3
4
5
6
7
Car.prototype.pa = 'diesel';
Car.prototype.getPa = function(){return this.pa;};
console.log(car.getPa()); // diesel

// create another Car instance
var audi = new Car("Audi");
console.log(audi.getPa()); // diesel

Example: OOP with classes ES6. ES6 provides specific syntax for defining the getter and setter using the get and set keywords. Properties are changed to _property to avoid the property collision with the getter and setter.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Person {
  // constructor
  constructor(name, height, weight) {
    this._name   = name;
    this._height = height;
    this._weight = weight;
  }
  // getter
  get bmi() {
    return this.calcBmi();
  }

  // setter
  set name(newName)     { this._name   = newName;   }  
  set height(newHeight) { this._height = newHeight; }  
  set weight(newWeight) { this._weight = newWeight; }

  // getter
  get name()   { return this._name;   }
  get height() { return this._height; }
  get weight() { return this._weight; }

  // method
  calcBmi() {
    return this._weight/(this._height/100 * this._height/100);
  }
}

// create one instance
const person = new Person("Alainen Kim", 290, 90);
console.log (person.name, person.height, person.weight, person.bmi);
// modify instance
person.name = "Teppo Testaaja";
person.height = 1000;
person.weight = 2000;
console.log (person.name, person.height, person.weight, person.bmi);

Will display following data:

1
2
3
4
5
6
7
8
"Alainen Kim"
290
90
10.70154577883472
"Teppo Testaaja"
1000
2000
20

Callback functions

  • callback function are given to another function as a parameter
  • another function can then call a callback function when needed
  • callback function are heavily used with eventhandling and asynchronous programming

Example with JavaScript setTimeout function:

1
2
3
4
5
6
function fn() {  
   console.log("Haloo");
}

// will print "Haloo" after one second
setTimeout(fn, 1000);

Example with own made functions:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
function fn1(name) {
  alert('Hello ' + name);
}

function fn2(name) {
  console.log('Hello ' + name);
}

function askName(callback) {
  // ask name
  let name = prompt('Write your name');
  // call callback function with name
  callback(name); 
}

askName(fn1);
// askName(fn2); // remember test this too! 

Arrow functions

  • Developer can use arrow functions in ES6
  • It is easy way to define function

A few examples

1
2
// traditional way to define a named function
function fn(a) { return a; }
1
2
// traditional way to define anonymous function
let afn = function(a) { return a; }
1
2
// arrow function
let lfn1 = (a) => a;
1
2
// arrow function, without () parenthesis,  if there are only one parameter
let lfn2 = a => a;
1
2
// arrow function without parameters
let lfn3 = () => { console.log("From lfn3"); };
1
2
3
// arrow function with multiple parameters
let lfn4 = (a, b) => a + b;
console.log(lfn4(-1, 5)); // prints: 4
1
2
3
4
5
// arrow function with multiple lines of code
let lfn5 = () => {
  console.log("From lfn5 row 1");
  console.log("From lfn5 row 2");
};
1
2
// arrow function as callbacks
setTimeout(() => console.log("Haloo"), 1000);

Arrow function and this keyword:

1
2
3
<body>
  <button>Click Me!</button>
</body>
1
2
3
4
5
6
7
8
9
let btn = document.querySelector('button');
const anofn = function () {
  return console.log(this);
}
var arfn = () => console.log(this);
// 1.
btn.addEventListener('click', anofn);
// 2.
//btn.addEventListener('click', arfn);
  • In 1. this keyword will point to [object HTMLButtonElement] -> a button object it self
  • In 2. this keyword will point to [object Window] -> object which defines arrow function

One common problem with traditional function and this keyword is visible in below code. You will need to define one more variable (like self) which points to function variables.

1
2
3
<body>
  <h3 id="count">0</h3>
</body>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function Counter() {
  this.number = 0;
  let self = this;
  setInterval(function() {
    self.number++;
    document.getElementById("count").innerHTML = self.number;
  }, 500); 
}

let counter = new  Counter();

You can avoid above problem using a arrow function instead of traditional named or anonymous function.

1
2
3
4
5
6
7
8
9
function Counter() {
  this.number = 0;
  setInterval(() => {
    this.number++;
    document.getElementById("count").innerHTML = this.number;
  }, 500);
}

let counter = new  Counter();

Function parameters

  • A JavaScript function does not perform any checking on parameter values (arguments)
  • Function parameters are the names listed in the function definition
  • Function arguments are the real values passed to (and received by) the function
  • JavaScript function definitions do not specify data types for parameters
  • JavaScript functions do not check the number of arguments received

If a function is called with missing arguments (less than declared), the missing values are set to undefined.

1
2
3
4
5
function myFunction(x, y) {
  if (y === undefined) {
    y = 2;
  }
}

ES6 allows default parameter values in the function declaration.

1
2
3
4
5
6
function fn1(n1, n2 = 2) {
  return n1 == n2;
}

console.log(fn1(3)); // false
console.log(fn1(2)); // true
1
2
3
4
5
6
7
8
function fn2(n1, n2 = n1) {
  console.log(n1); // 4
  console.log(n2); // 5
  return n1 == n2;
}

console.log(fn2(4, 5)); // false, because n2 = n1 doesn't happen, two parameters
console.log(fn2(4));    // true, because n2 = n1 will be called (only one parameter)

Template Literals

Template Literals use back-ticks (``) rather than the quotes ("") to define a string.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
let firstname = 'Pekka';
let lastname = "Pouta";

let multiline = `
ES5 is ok,
ES6 rules ok
`;
console.log(multiline);

let hello = `Helou, I'm ${lastname} ${firstname}`;
console.log(hello);

Will print:

1
2
3
4
5
"
ES5 is ok,
ES6 rules ok
"
"Helou, I'm Pouta Pekka"

Object literals

Variables can have default values to object fields.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
let name = "John";
let age = 50;

let object = {
 name : 'Ari',
 age,
 fn() {
  console.log(this.name + ', ' + this.age)
 }
}

console.log(object);
object.fn();

Will print:

1
2
3
4
5
6
7
8
9
[object Object] {
  age: 50,
  fn: fn() {
  window.runnerWindow.proxyConsole.log(this.name + ', ' + this.age)
 },
  name: "Ari"
}

"Ari, 50"

Developer can write it more easily:

1
2
3
4
5
let name = 'Ari';
let age = 50;

let object = {name, age};
console.log(object.name); // "Ari"

Dynamic fields

Object field names can be created dynamically using [].

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
let counter = 0;
let getId = () => ++counter;

let object1 = {
  ['id_' + getId()]: counter
};

let object2 = {
  ['id_' + getId()]: counter
};

console.log(object1); // [object Object]{id_1: 1}
console.log(object2.id_2); // "2"

Rest operator ...array

Function parameters (list) are moved to array.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function calculateSum(...values) { // array in here
  console.log(values);
  let sum = 0;
  for(let i = 0; i < values.length; i++) {
    sum += values[i];
  }
  return sum;
}

console.log(calculateSum(10,20,30)); // list in here

Spread operator ...list

Array in function parameters are moved to list.

1
2
3
4
5
6
7
8
let values  = [1,2,3];
console.log(...values); // 1
                        // 2
                        // 3
console.log(values);    // [1,2,3]

// Math requires a list, convert array to list with spread operator
console.log(Math.max(...values)); // 3

Array items to variables

Array values can be moved to varibles.

1
2
3
4
5
6
let numbers = [1, 2, 3];

let [n1, n2, n3] = numbers;
console.log(n1); // 1
console.log(n2); // 2
console.log(n3); // 3
1
2
3
4
5
let numbers = [1,2,3]
let [a,...b] = numbers;

console.log(a); // 1
console.log(b); // [2, 3]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
let object = {
  name: 'Ari',
  age: 53
};

 // nimi-field renaming to name

let { name: firstname, age } = object; // firstname is a new alias

console.log(firstname); // "Ari"
console.log(age); // "53"
console.log(name); // "error"