Functions: LevelUP

Call stack

function first() {
  // Inside first function'
  second();
  // Again inside first function
}

function second() {
  // Inside second function
  return 'Hello World!'
}

// Inside Global Execution Context

first();

// Again inside Global Execution Context

Scope

function exampleFunction() {
    var x = "declared inside function";  // x can only be used in exampleFunction
    console.log("Inside function");
    console.log(x);
}

console.log(x);  // Causes error
var x = "declared outside function";

exampleFunction();

function exampleFunction() {
    console.log("Inside function");
    console.log(x);
}

console.log("Outside function");
console.log(x);

Closures

A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). In other words, a closure gives you access to an outer function’s scope from an inner function. In JavaScript, closures are created every time a function is created, at function creation time.

Closures

let name = "John";

function sayHi() {
  return `Hi ${name}`;
}

name = "Pete";

console.log(sayHi()); // "John" or "Pete"?

Closures

function makeWorker() {
  let name = "Pete";

  return function() {
    return `Hi ${name}`;
  };
}

let name = "John";

// create a function
const sayHi = makeWorker();

// call it
console.log(sayHi()); // "John" or "Pete"?

Closures

const users = [
  { firstName: 'John', lastName: 'Smith' },
  { firstName: 'Todd', lastName: 'Lee' },
  { firstName: 'Taylor', lastName: 'Fox' },
];

for (let i = 0; i < users.length; i++) {
  var user = users[i];

  user.getFullName = () => (
    `${user.firstName} ${user.lastName}`
  );
}

console.log(users[0].getFullName()); // ?
console.log(users[1].getFullName()); // ?
console.log(users[2].getFullName()); // ?

Closures

const users = [
  { firstName: 'John', lastName: 'Smith' },
  { firstName: 'Todd', lastName: 'Lee' },
  { firstName: 'Taylor', lastName: 'Fox' },
];

const getFullName = (firstName, lastName) => () => (
  `${firstName} ${lastName}`
);

for (let i = 0; i < users.length; i++) {
  var user = users[i];
  user.getFullName = getFullName(user.firstName, user.lastName);
}

console.log(users[0].getFullName()); // 'John Smith'
console.log(users[1].getFullName()); // 'Todd Lee'
console.log(users[2].getFullName()); // 'Taylor Fox'

Self-Invoking functions

(function (text) {
  console.log(text);  // 'Hello World!'
})('Hello World!');

// or

(text => {
  console.log(text);  // 'Hello World!'
})('Hello World!');

Recursive function

function pow(x, n) {
  if (n === 1) {
    return x;
  } else {
    return x * pow(x, n - 1);
  }
}

console.log(pow(2, 3)); // 8

Unit testing

In computer programming, unit testing is a software testing method by which individual units of source code, sets of one or more computer program modules together with associated control data, usage procedures, and operating procedures, are tested to determine whether they are fit for use. [Wikipedia]

Unit Testing Tools

Use realistic input

An example of using Jest

function addProduct(name, price) {
  const productNameRegexNoSpace = /^\S*$/g; // no white-space allowed

  if (!productNameRegexNoSpace.test(name)) {
    return false;
  }

  return typeof price === 'number';
}

test('When adding new valid product, get successful confirmation', () => {
  const name = faker.commerce.productName();
  const price = faker.random.number();

  // Generated random input: { 'Sleek Cotton Computer',  85481 }
  expect(addProduct(name, price)).toBe(true);
  // Test failed, the random input triggered some path we never planned for.
  // We discovered a bug early!
});

Links

Functions: LevelUP

By Andrew Bogomolov

Functions: LevelUP

lesson 5 (JavaScript)

  • 73