JavaScript & TypeScript examples in OJS

Since all of these code examples are run in Observable JS, they are contained in outer {} and the return object is what gets printed to the screen, rather than using console.log. In some cases I leave in the console.log, but usually I try to get rid of it.

JavaScript Introduction

Regular function

{
  var getRegular = function() {
    return 10;
  }
  return getRegular();
}

Arrow function with no parameters

{
  const getArrow = () => 10;
  return getArrow();
}

Arrow function with one parameter

{
  const getArrow = m => 10*m;
  return getArrow(2);
}

Arrow function with multiple parameters

{
  const getArrow = (m, bonus) => 10*m + bonus;
  return getArrow(2, 20);
}

Test for equality and inequality

{
  let a = 4;
  var b = 5;
  return [a == b, a < b, a > b, a !== b];
}

this keyword with regular function out of scope inside setTimeout and need to re-assign to self

{
  let output;
  var employee = {
    id: 1,
    greet: function(){
      var self = this;
      setTimeout(function(){ console.log(self.id) }, 1000);
      return self.id;
    }
  };
  return employee.greet();
}

this keyword with arrow function does not go out of scope inside setTimeout so we don’t need to re-assign to self

{
  let output;
  var employee = {
    id: 1,
    greet: function(){
      setTimeout(() => { console.log(this.id) }, 1000);
      return this.id;
    }
  };
  return employee.greet();
}

rest operator (… in function parameter)

{
  let displayColors = function(msg, ...colors){
    for(let i in colors){
      console.log(colors[i])
    }
    return colors[0];
  }
  
  let msg1 = "List of colors";
  return displayColors(msg1, 'Red', 'Blue', 'Green');
}

spread operator (… in function call)

{
  let displayColors = function(msg, ...colors){
    for(let i in colors){
      console.log(colors[i])
    }
    return colors[0];
  }
  
  let msg2 = "List of colors";
  let colorArray = ['Orange','Yellow','Indigo'];
  return displayColors(msg2, ...colorArray);
}

A const object cannot be re-assigned, but you can change its property.

{
  const obj1 = {
    name:"Chandler"
  }
  obj1.name = "Todd"
  return obj1.name;
}

In shorthand notation in properties and function assignment.

{
  let firstname = "Chandler";
  let lastname = "Bings";
  
  let person = {
    firstname,
    lastname
  };
  
  function createPerson(firstname, lastname, age){
    let fullname = firstname + " " + lastname;
    return {firstname, 
            lastname, 
            fullname, 
            isBoomer(){
              return age>60;
            }}
  }
  
  let p = createPerson("Ross", "Geller", 32);
  return p
}

You can use spaces in property names and use variables, but you have to use square brackets [ ].

{
  let ln = "last name";
  let person = {
    "first name": "Chandler",
    [ln]: "Bing"
  };
  return person
}

Destructruing arrays can be used to break them apart

{
  let employee = ["Chandler", "Bing"," Male"];
  let [, , gender] = employee;

  return gender
}

Destructruing arrays using the rest operator

{
  let employee = ["Chandler", "Bing"," Male"];
  let [fname, ...elements] = employee;

  return elements
}

Destructruing arrays using the rest operator

{
  let employee = ["Chandler", "Bing"];
  let [fname, lastname, gender = "Female"] = employee;

  return gender
}

Destructruing objects with aliases

{
  let employee = {
    fname: "Chandler",
    lname: "Bing",
    gender: "Male"
  };

  let {fname: f, lastname: l, gender: g} = employee;

  return g
}

Using string templates to use variables inside a string

{
  let employee = {
    fname: "Chandler",
    lname: "Bing",
    gender: "Male"
  };

  let greet = `Welcome ${employee.fname} to 'single' "double" ES2015
                This is the second line
                Third and so on`;

  return greet
}

Using for of loop with array or string

{
  let colors = ['Red','Blue','Green'];
  for(let color of colors){
    console.log(colors)
  }
}

Classes (are not hoisted)

{
  class Person{
    greet(){}
  }
  let p = new Person();

  return p.greet === Person.prototype.greet;
  
}

Class body and methods

{
  class Person{
    constructor(name){
      this.name = name;
    }
    static staticMethod(){
      console.log("Static Mehod");  
    }
    greetPerson(){
      console.log("Hello " + this.name);  
    }
  }

  let p = new Person("Chandler");
  Person.staticMethod();
  p.greetPerson;
  
  return p;
}

Classs ineritance: The child class need to use keyword super to access to methods deployed in the parent class.

{
  class Person{
    constructor(name){
      <!-- this.name = name; -->
      console.log(name + "Person constructor");
    }
    getID(){
      return 10;
    }
  }
  
  class Employee extends Person{
    constructor(name){
      super(name)
      console.log(name + "Employee constructor");
    }
    getID(){
      return super.getID();
    }
  
  }
  
  let e = new Employee("Chandler");
  return e.getID();
}

Sets are unique and maps are not. In maps, objects are strings, so if we want to access myMap[100], we have to use myMap[“100”].

{
  let mySet = Object.create(null);
  
  mySet.id = true;
  if(mySet.id){
    console.log("id exists");
  }
  
  let myMap = Object.create(null);
  myMap.name = "Chandler";
  
  myMap[100] = 'Hello';

  return myMap["100"];
}

We can access myMap using obj2 even though it was not set because the representation of obj2 matches that of obj1.

{
  let obj1 = {};
  let obj2 = {};
  
  let myMap = Object.create(null);
  myMap[obj1] = 'World';

  return myMap[obj2];
}

You can use add, delete, has, and size with sets. Sets are unique, so duplicates are ignored.

{
  let mySet = new Set();
  let obj1 = {};
  let obj2 = {};

  mySet.add("Hello").add(2);
  
  mySet.delete(2);
  
  mySet.add(2);
  mySet.add(2);
  mySet.add(2);
  mySet.add(2);
  
  mySet.add(obj1);
  mySet.add(obj2);
  
  return [mySet.size, mySet.has(2)];
}

Map is similar, but use set instead of add. There is also WeakMap where the keys can only be objects.

{
  let myMap = new Map();
  myMap.set("fname","Chandler");
  myMap.set("age", 30);
  
  let obj1 = {};
  let obj2 = {};
  
  myMap.set(obj1, 10);
  myMap.set(obj2, 20);
  
  myMap.delete(obj2);
  
  // myMap.clear(); // removes everything in the map
  
  return [myMap.get(obj1), myMap.has("fname"), myMap.size];
}

Example of using both keys and values in a Map.

{
  let myMap = new Map([
    ["fname", "Chandler"],
    ["lname", "Bing"]
  ]);
  
  let out1;
  for(let [key, value] of myMap.entries()){
    out1 = `${key} -> ${value}`;
  }
  
  let out2;
  for(let value of myMap.values()){
    out2 = value;
  }
  
  let out3
  for(let key of myMap.keys()){
    out3 = key;
  }
  
  return [out1, out2, out3];
}

forEach can only be used with arrays, maps, and sets.

{
  let out1;
  let out2;
  let out3;
  
  var numbers = [2,4,6,8]
  numbers.forEach(arrayFunction);
  function arrayFunction(element, index, array){
    out1 = "arr[" + index + "] = " + element;
  }

  let myMap = new Map([
    ["fname", "Chandler"],
    ["lname", "Bing"]
  ]);

  myMap.forEach(mapFunction);
  function mapFunction(value, key, callingMap){
    out2 = key + " = " + value;
    console.log(myMap === callingMap);
  }

  let mySet = new Set([1,2,3]);
  mySet.forEach(setFunction);
  function setFunction(value, key, callingSet){
    out3 = key + " = " + value;
    console.log(mySet === callingSet);
  }

  return [out1, out2, out3];
}

Symbols create a unique id, but we can’t see what the id is. Even though s2 and s3 have the same name, the id is different.

{
  let s = Symbol("First Symbol");
  
  let s2 = Symbol("Test");
  let s3 = Symbol("Test");
  
  return [typeof s, s.toString(), s2===s3];
}

We can register the name using Symbols.for and then the ids will be the same.

{
  let s4 = Symbol.for('RegSymbol');
  let s5 = Symbol.for('RegSymbol');

  return [s4===s5, Symbol.keyFor(s4)];
}

Symbols create a unique id, but we can’t see what the id is.

{
  let fname = Symbol("FirstName");
  
  let person = {
    [fname]: "Chandler"
  };
  
  return [Object.getOwnPropertySymbols(person)];
}

for..of –> iterator method –> symbol.iterator can only be used with strings and arrays, because they are functions.

{
  let str = "Hello";
  let arr=[1,2,3];
  let num=5;
  let obj = {name:"Chandler"};

  return ["For string - " + typeof str[Symbol.iterator],
          "For array - " + typeof arr[Symbol.iterator],
          "For number - " + typeof num[Symbol.iterator],
          "For object - " + typeof obj[Symbol.iterator]];
}

Here is how an iterator works:

Iterable { symbol.Iterator : Iterator }

Iterator{ next() : IResultObj }

IResultObj{ value: any done: bool }

As an example, let’s create our own iterator.

{
  let iterable = [1,2,3];
  
  function createIterator(array){
    let count = 0;
    return{
      next: function(){
        return count < array.length?
        {value: array[count++], done:false}:
        {value: undefined, done:true};
      }
    }
  }
  
  let myIterator = createIterator(iterable);

  return [myIterator.next(),
          myIterator.next(),
          myIterator.next(),
          myIterator.next()];  
}

for..of doesn’t work with objects, so we have to build our own iterator using the example above.

{
  let person = {
    fname: "Chandler",
    lname: "Bing"
  };
  
  // for (let p of person) {} // doesn't work, yields type error
  
  person[Symbol.iterator] = function(){
    let properties = Object.keys(person);
    let count = 0;
    let isDone = false;
    let next = () => {
      if(count >= properties.length){
        isDone = true;
      }    
      return{done: isDone, value: this[properties[count++]]};
    }
    return {next};
  }

  return [person[Symbol.iterator]];  
}

Generators allow pausing of functions using yield and then resuming.

{
  
  function *createGenerator(){
    yield 1;
    console.log("After 1st yield");
    yield 2;
  };

  let myGen = createGenerator();
  
  return [myGen.next(), myGen.next(), myGen.next()];  
}

We can use a generator to simplfy the object iterator coded above.

{
  let person = {
    fname: "Chandler",
    lname: "Bing"
  };
  
  person[Symbol.iterator] = function*(){
    let properties = Object.keys(person);
    for(let t of properties){
      yield this[t];
    }
  };
  
  let out;
  for (let p of person){
    console.log(p);
    out = p;
  }
  
  return out;  
}

JavaScript Quiz Time

How long does this code take to run? 10 seconds, or immediately?

{
  const start = Date.now();
  let modal = document.querySelector('#result');
  setTimeout(function () {
    modal.classList.remove('hidden');
  }, 10_000);
  const end = Date.now();
  return[start, end];
}

What is returned by these statements?

{
  let cat = Object.create({ type: 'lion' });
  cat.size = 'large';
  
  let copyCat = { ...cat };
  cat.type = 'tiger';
  
  return [copyCat.type, copyCat.size];
}

What value does this statement return?

{
  let animals = [{ type: 'lion' }, 'tiger'];
  let clones = animals.slice();
  
  clones[0].type = 'bear';
  clones[1] = 'sheep';
  
  return [animals[0].type, clones[0].type, animals[1], clones[1]];
}

What does this function return?

{
  let cat = { type: "tiger", size: "large" };
  let json = JSON.stringify(cat, ["type"]);
  
  return json;
}

What is the output of { first: 20, second: 30, first: 50 }?

{
  const obj1 = { first: 20, second: 30, first: 50 };
  return obj1;
}

What is the type of NaN?

{
  return print(typeof NaN);;
}

What is the output of 5 + “9”?

{
  return 5 + "9";
}

What is the total of this function call?

{
  function sum(num1, num2 = 2, num3 = 3) {
    return num1 + num2 + num3;
  }
  let values = [1, 5];
  let total = sum(4, ...values);
  return total;
}

Which statement(s) are true?

{
  return [Boolean(NaN), Boolean(0), Boolean("false"), Boolean("")];
}

Accessing variable properties: What is the output of bob.precip?

{
  var Storm = function () {};
  Storm.prototype.precip = 'rain';
  var WinterStorm = function () {};
  WinterStorm.prototype = new Storm();
  WinterStorm.prototype.precip = 'snow';
  var bob = new WinterStorm();
  
  return(bob.precip);
}

Print 1, 2, 3, 4 to the console.

{
  let out = []
  for (var i = 1; i <= 4; i++) {
    (function (j) {
      setTimeout(function () {
        console.log(j);
        out.push(j);
      }, j * 1000);
    })(i);
  }
  return out;
}

What is the reult of this function call?

{
  var compare = function (test1, test2) {
    return test1==test2;
  };

  return compare(1078, '1078');
}

More equality tests to consider

{
  let a = 1078;
  let b = '1078';
  
  return [a == b, a === b, a != b, a !== b]
}

Check if the word “pot” is in the word “potato”?

{
  return "potato".includes("pot");
}

What does this function return?

{
  let bear = {
    sound: 'roar',
    roar() {
      console.log(this.sound);
    },
  };
  
  bear.sound = 'grunt';
  let bearSound = bear.roar;
  
  return bearSound();
}

What does this function return?

{
  var cat = { name: 'Athena' };
  
  function swap(feline) {
    feline.name = 'Wild';
    feline = { name: 'Tabby' };
  }
  swap(cat);

  return cat.name;
}

What does this function return?

{
  let out = [];
  var thing;
  let func = (str = 'no arg') => {
    out.push(str);
  };
  func(thing);
  func(null);
  
  return out;
}

What does this function return?

{
  const myFunc = () => {
    const a = 2;
    return () => console.log('a is ' + a);
  };
  const a = 1;
  const test = myFunc();

  return test();
}

Which flag does this statement return?

{
  var flagsJSON =
    '{ "countries" : [' +
    '{ "country":"Ireland" , "flag":"🇮🇪" },' +
    '{ "country":"Serbia" , "flag":"🇷🇸" },' +
    '{ "country":"Peru" , "flag":"🇵🇪" } ]}';
  var flagDatabase = JSON.parse(flagsJSON);
  
  return flagDatabase.countries[0].flag;
}

How to condition on two variables

{
  let conservation = true;
  let deforestation = false;
  let acresOfRainForest = 100;
  if (conservation && !deforestation) {
      ++acresOfRainForest;
  }
  return acresOfRainForest;
}

What does this function return?

{
  'use strict';
  function logThis() {
    this.desc = 'logger';
    console.log(this);
  }
  
  return new logThis();
}

What does the following expression evaluate to?

{
  return [] == [];
}

In OJS this returns undefined, but in JavaScript it returns 1.

{
  var v = 1;
  var f1 = function () {
    return v;
  };
  
  var f2 = function () {
    var v = 2;
    f1();
  };

  return f2();
}

What will the value of y be in this code:

{
  const x = 6 % 2;
  const y = x ? 'One' : 'Two';
  
  return y;
}

What does this function return?

{
  let answer = true;
  if (answer === false) {
    return 0;
  } else {
    return 10;
  }
}

What does this function return?

{
  function sayHello() {
    console.log('hello');
  }
  
  return sayHello.prototype;
}

This code works in OJS, but in JavaScript you would get TypeError: diff is not a function.

{
  function sum(x, y) {
    return x + y;
  }
  
  let diff = function (x, y) {
    return x - y;
  };

  return [sum(10, 20), diff(10, 20)];
}

What happens when you run this code?

{
  var a = ['dog', 'cat', 'hen'];
  a[100] = 'fox';

  return a.length;
}

What does this function return?

{
  function logThis() {
    return this;
  }

  return logThis();
}

What does this function return?

{
  const foo = [1, 2, 3];
  const [n] = foo;

  return n;
}

What does this function return?

{
  let rainForests = ['Amazon', 'Borneo', 'Cerrado', 'Congo'];
  rainForests.splice(0, 2);
  
  return rainForests;
}

What does this function return?

{
  const obj = {
    a: 1,
    b: 2,
    c: 3,
  };
  
  const obj2 = {
    ...obj,
    a: 0,
  };

  return [obj2.a, obj2.b];
}

What does this function return?

{
  let animals = ['jaguar', 'eagle'];

  return [animals.pop(), animals.reverse(), animals.shift(), animals.pop()];
}

What does this function return?

{
  const animals = ['Rabbit', 'Dog', 'Cat'];
  animals.unshift('Lizard');
  
  return animals;
}

What does this function return?

{
  const arr1 = [2, 4, 6];
  const arr2 = [3, 5, 7];

  return [...arr1, ...arr2];
}

What does this function return?

{
  const myNumbers = [1, 2, 3, 4, 5, 6, 7];
  const myFunction = (arr) => {
    return arr.map((x) => x + 3).filter((x) => x < 7);
  };
  
  return myFunction(myNumbers);
}

What does this function return?

{
  let rainForestAcres = 10;
  let animals = 0;
  
  while (rainForestAcres < 13 || animals <= 2) {
    rainForestAcres++;
    animals += 2;
  }

  return animals;
}

What does this function return?

{
  let cipherText = [...'YZOGUT QGMORTZ MTRHTILS'];
  let plainText = '';

  for (let [index, value] of cipherText.entries()) {
   plainText += index % 2 === 0 ? value : '';
  }
  
  return plainText;
}

What does this function return?

{
  var pokedex = ['Snorlax', 'Jigglypuff', 'Charmander', 'Squirtle'];
  pokedex.pop();
  
  return pokedex.pop();
}

Which value is not falsey?

{
  return [[] == false, undefined == false, 0 == false, null == false];
}

What does this function return?

{
  const person = { name: 'Dave', age: 40, hairColor: 'blue' };
  const result = Object.keys(person).map((x) => x.toUpperCase());
  
  return result;
}

What does this function return?

{
  let animals = ["eagle", "osprey", "salmon"];
  let key = animal => animal === "salmon";

  if (animals.some(key)) {
    return "swim";
  }
}

Given this code, which statement(s) will evaluate to false?

{
  const a = { x: 1 };
  const b = { x: 1 };
  
  return [a['x'] === b['x'], a != b, a === b, a.x === b.x];
}

What does this function return?

{
  return [typeof 41.1, typeof 41.0, typeof 41, typeof "41"];
}

What does this function return?

{
  let scores = [];
  scores.push(1, 2);
  scores.pop();
  scores.push(3, 4);
  scores.pop();
  let score = scores.reduce((a, b) => a + b);
  
  return score;
}

TypeScript

The rest of the examples are TypeScript features, which will not work in OJS, but hopefully you get the point by looking at the code examples.

{
  // type inference
  var x = 10;
  var y = "hi";
  var z = true;
  
  // explicit stating of type in TypeScript 
  // var a: number = 10;
  // var b: string;
    
  return [typeof x, typeof y, typeof z];  
}

The following codes runs just fine in JS, but would not run in TS because n1 is of type number so it cannot be set to type string.

{
  var n1 = 10;
  
  n1 = "Hi";
  
  return n1;
}

Even in TS, the following works because concatenating a number and a string produces a number, so n2 is a string and TS is fine with that..

{
  var n1 = 10;
  
  var n2 = n1 + "Hello";
  
  return [n2, typeof n2];
}

TS has a new variable type called any which doesn’t have any type checking.

var info: any;
info = 10;
info = "Hello";
info = true;

enum provides a user-friendly value for variables.

{
  enum EyeColor {Brown=1, Black=5, Blue=10};

  var myEyeColor = EyeColor.Brown;

  return myEyeColor;
}

Arrays in TS work the same as in JS. tuples allow you to limit the types that can be stored.

let strArr1: string[] = ['Hello','World'];
let strArr2: Array<string> = ['Hello','World'];

let anyArr: any[] = ['Hello', 10, true];

let myTuple: [string, number] = ["Hi", 10];
myTuple[2] = 100;

Class constructors in TS

// in JavaScript
class Person{
  public fname: string;
  public lname: string;
  constructor(fname: string, public lname: string){
    this.fname = fname;
    this.lname = lname;
  }
};

// in TypeScript
class Person1{
  constructor(public fname: string, public lname: string){}
}

Interfaces are the most flexible way to describing types in TS. Use ? to make a property optional.

interface Person{
  fname: string;
  lname: string;
  age?: number;
}

let employee1: Person = {
  fname:"Chandler",
  lname:"Bing",
  age:30
}

let emplyee2: Person = {
  fname:"Ross"
  lname:"Geller"
}

Decorators are experimental in TS and may change in the future. Decorators begin with the @ symbol.

@Component({
  selector: 'my-app',
  template: <h1>Parity Technologies</h1>
})
export class AppComponent {
  }