Mind~G
Javascript

Functions

A function in JavaScript is a piece of code that you can use again and again. Think of it like a recipe. Once you write the recipe, you can cook the same dish many times without writing the instructions again.

Why do we need functions

  1. To reuse code instead of writing the same thing many times
  2. To organize code into smaller pieces
  3. To make code easier to read and understand
  4. To avoid mistakes by keeping logic in one place

Function Declaration

A function declaration is the traditional way to create a function using the function keyword.

function greet(name) {
  return "Hello " + name
}
 
console.log(greet("John"))

Important things about function declaration

  1. You can call the function before you write it because of hoisting
  2. The function gets fully hoisted with all its code
  3. You must give it a name

Example of hoisting

sayHello()
 
function sayHello() {
  console.log("Hello")
}

This works fine because the function is hoisted to the top.

Function Expression

A function expression is when you create a function and store it in a variable.

const greet = function(name) {
  return "Hello " + name
}
 
console.log(greet("John"))

Important things about function expression

  1. You cannot call it before you write it
  2. Only the variable name gets hoisted, not the function code
  3. The function can have a name or be anonymous

Example that will fail

sayHello()
 
const sayHello = function() {
  console.log("Hello")
}

This will give an error because sayHello is not a function yet.

Function Declaration vs Function Expression

This is a very common interview question. You must understand the difference.

Function Declaration

function add(a, b) {
  return a + b
}
  1. Starts with the function keyword
  2. Must have a name
  3. Gets hoisted completely
  4. You can call it before writing it

Function Expression

const add = function(a, b) {
  return a + b
}
  1. Function is stored in a variable
  2. Can be anonymous or named
  3. Only variable gets hoisted, not the function
  4. You cannot call it before writing it

When to use which one

Use function declaration when you want the function available everywhere in your code.

Use function expression when you want more control over when the function is created.

Arrow Functions

Arrow functions are a shorter way to write functions. They were added in ES6.

Regular function

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

Arrow function

const add = (a, b) => {
  return a + b
}

Even shorter arrow function

const add = (a, b) => a + b

When your function only returns one thing, you can remove the curly braces and the return keyword.

Arrow function with one parameter

const double = num => num * 2

When you have only one parameter, you can remove the parentheses too.

Arrow function with no parameters

const greet = () => "Hello"

When you have no parameters, you must keep the parentheses.

Lexical this in Arrow Functions

This is extremely important for interviews. Arrow functions do not have their own this. They use the this from the place where they were written. This is called lexical this.

Regular function example

const person = {
  name: "John",
  greet: function() {
    setTimeout(function() {
      console.log("Hello " + this.name)
    }, 1000)
  }
}
 
person.greet()

This will print "Hello undefined" because the function inside setTimeout has its own this which is not the person object.

Arrow function example

const person = {
  name: "John",
  greet: function() {
    setTimeout(() => {
      console.log("Hello " + this.name)
    }, 1000)
  }
}
 
person.greet()

This will print "Hello John" because the arrow function does not have its own this. It uses the this from the greet function which is the person object.

Important points about arrow functions and this

  1. Arrow functions do not have their own this
  2. They inherit this from the parent scope
  3. This is called lexical this or lexical scoping
  4. You cannot change this in an arrow function using bind, call, or apply
  5. Arrow functions are perfect for callbacks because they keep the correct this

When not to use arrow functions

Do not use arrow functions as methods in objects.

const person = {
  name: "John",
  greet: () => {
    console.log("Hello " + this.name)
  }
}
 
person.greet()

This will not work because arrow functions do not have their own this. The this here will be the global object, not the person object.

Higher Order Functions

A higher order function is a function that takes another function as an argument or returns a function. This sounds complicated but it is actually simple.

Example of taking a function as argument

function doSomething(callback) {
  console.log("Doing something")
  callback()
}
 
function sayDone() {
  console.log("Done")
}
 
doSomething(sayDone)

Here doSomething is a higher order function because it takes another function as an argument.

Example of returning a function

function makeMultiplier(multiplier) {
  return function(number) {
    return number * multiplier
  }
}
 
const double = makeMultiplier(2)
console.log(double(5))

Here makeMultiplier is a higher order function because it returns another function.

Array Methods: map, filter, reduce

These are the most important higher order functions in JavaScript. They are built into arrays and they are asked in almost every interview.

map

The map method creates a new array by calling a function on every element in the original array.

Think of map like a factory. You put items in, the factory does something to each item, and you get new items out.

Example

const numbers = [1, 2, 3, 4, 5]
 
const doubled = numbers.map(function(num) {
  return num * 2
})
 
console.log(doubled)

Output: [2, 4, 6, 8, 10]

With arrow function

const numbers = [1, 2, 3, 4, 5]
const doubled = numbers.map(num => num * 2)
console.log(doubled)

Real world example

const users = [
  { name: "John", age: 25 },
  { name: "Jane", age: 30 },
  { name: "Bob", age: 35 }
]
 
const names = users.map(user => user.name)
console.log(names)

Output: ["John", "Jane", "Bob"]

Important points about map

  1. It returns a new array
  2. The new array has the same length as the original
  3. It does not change the original array
  4. You must return something from the callback

filter

The filter method creates a new array with only the elements that pass a test.

Think of filter like a security guard. Only items that meet the requirement can pass through.

Example

const numbers = [1, 2, 3, 4, 5, 6]
 
const evenNumbers = numbers.filter(function(num) {
  return num % 2 === 0
})
 
console.log(evenNumbers)

Output: [2, 4, 6]

With arrow function

const numbers = [1, 2, 3, 4, 5, 6]
const evenNumbers = numbers.filter(num => num % 2 === 0)
console.log(evenNumbers)

Real world example

const users = [
  { name: "John", age: 25 },
  { name: "Jane", age: 17 },
  { name: "Bob", age: 35 }
]
 
const adults = users.filter(user => user.age >= 18)
console.log(adults)

Output: [{ name: "John", age: 25 }, { name: "Bob", age: 35 }]

Important points about filter

  1. It returns a new array
  2. The new array may be shorter than the original
  3. It does not change the original array
  4. The callback must return true or false
  5. If true, the item is included in the new array
  6. If false, the item is not included

reduce

The reduce method takes all elements in an array and combines them into a single value.

Think of reduce like a blender. You put many fruits in, and you get one smoothie out.

Example

const numbers = [1, 2, 3, 4, 5]
 
const sum = numbers.reduce(function(accumulator, currentValue) {
  return accumulator + currentValue
}, 0)
 
console.log(sum)

Output: 15

How reduce works step by step

  1. First time: accumulator is 0, currentValue is 1, return 0 + 1 = 1
  2. Second time: accumulator is 1, currentValue is 2, return 1 + 2 = 3
  3. Third time: accumulator is 3, currentValue is 3, return 3 + 3 = 6
  4. Fourth time: accumulator is 6, currentValue is 4, return 6 + 4 = 10
  5. Fifth time: accumulator is 10, currentValue is 5, return 10 + 5 = 15

With arrow function

const numbers = [1, 2, 3, 4, 5]
const sum = numbers.reduce((acc, curr) => acc + curr, 0)
console.log(sum)

Real world example

const cart = [
  { item: "Shirt", price: 500 },
  { item: "Pants", price: 1000 },
  { item: "Shoes", price: 2000 }
]
 
const total = cart.reduce((sum, product) => sum + product.price, 0)
console.log(total)

Output: 3500

Important points about reduce

  1. It returns a single value
  2. It takes two parameters: callback function and initial value
  3. The callback gets two arguments: accumulator and current value
  4. Accumulator stores the result as you go through the array
  5. Current value is the item you are currently looking at
  6. The initial value (0 in our example) is optional but recommended

Chaining Array Methods

You can chain map, filter, and reduce together to do powerful operations.

Example

const numbers = [1, 2, 3, 4, 5, 6]
 
const result = numbers
  .filter(num => num % 2 === 0)
  .map(num => num * 2)
  .reduce((sum, num) => sum + num, 0)
 
console.log(result)

This code does three things:

  1. Filter: Get only even numbers [2, 4, 6]
  2. Map: Double each number [4, 8, 12]
  3. Reduce: Add them all together 4 + 8 + 12 = 24

Output: 24

Real world example

const products = [
  { name: "Laptop", price: 50000, inStock: true },
  { name: "Phone", price: 20000, inStock: false },
  { name: "Tablet", price: 30000, inStock: true },
  { name: "Watch", price: 10000, inStock: true }
]
 
const total = products
  .filter(product => product.inStock)
  .map(product => product.price)
  .reduce((sum, price) => sum + price, 0)
 
console.log(total)

This code calculates total price of all products that are in stock.

  1. Filter: Get only products in stock
  2. Map: Get just the prices
  3. Reduce: Add all prices together

Output: 90000

Interview Tips

When talking about functions in interviews, remember these points:

For function declaration vs expression

  1. Function declaration gets hoisted, expression does not
  2. Declaration needs a name, expression can be anonymous
  3. You can call declaration before writing it
  4. Expression gives you more control

For arrow functions

  1. Arrow functions are shorter syntax
  2. They do not have their own this
  3. They use lexical this from parent scope
  4. Perfect for callbacks and array methods
  5. Do not use them as object methods

For higher order functions

  1. A function that takes a function as argument or returns a function
  2. Makes code more reusable and clean
  3. map, filter, reduce are built in higher order functions

For map, filter, reduce

  1. map transforms each element
  2. filter selects some elements
  3. reduce combines all elements into one value
  4. All three return new values and do not change original array
  5. You can chain them together

Common Interview Questions

Question 1: What is the difference between function declaration and function expression?

Good Answer: Function declaration starts with the function keyword and has a name. It gets hoisted completely so you can call it before you write it. Function expression is when you store a function in a variable. Only the variable gets hoisted but not the function, so you cannot call it before writing it. Function declaration is good when you want the function available everywhere. Function expression gives you more control over when the function is created.

Question 2: What is lexical this in arrow functions?

Good Answer: Arrow functions do not have their own this. They use the this from the place where they were written. This is called lexical this. For example, if you use an arrow function inside a method, it will use the this from that method. This is very useful for callbacks like setTimeout where regular functions lose the correct this. However, you should not use arrow functions as object methods because they will not have the correct this.

Question 3: What is a higher order function?

Good Answer: A higher order function is a function that either takes another function as an argument or returns a function. For example, the map method is a higher order function because it takes a function as an argument. Another example is when you create a function that returns another function. Higher order functions make code more reusable and clean.

Question 4: Explain map, filter, and reduce.

Good Answer: map creates a new array by transforming each element using a function. filter creates a new array with only elements that pass a test. reduce combines all elements into a single value by running a function on each element. All three do not change the original array. map is for transforming, filter is for selecting, and reduce is for combining.

Question 5: Does arrow function have its own this?

Good Answer: No, arrow functions do not have their own this. They inherit this from the parent scope where they were defined. This is called lexical this. You cannot change the this of an arrow function using bind, call, or apply. This makes arrow functions perfect for callbacks but not good for object methods.

Question 6: When should you use arrow functions?

Good Answer: Use arrow functions for callbacks, array methods like map and filter, and when you want to keep the parent this. Do not use arrow functions as methods in objects or as constructors. Arrow functions are great for short functions and when you need lexical this.

Question 7: What does map return?

Good Answer: map returns a new array with the same length as the original array. Each element in the new array is the result of calling the provided function on each element of the original array. It does not change the original array. If the original array has 5 elements, the new array will also have 5 elements.

Question 8: What does filter return?

Good Answer: filter returns a new array containing only the elements that pass the test provided by the callback function. The callback must return true or false. If true, the element is included. If false, it is not included. The new array may be shorter than the original. It does not change the original array.

Question 9: What does reduce return?

Good Answer: reduce returns a single value. It goes through each element in the array and combines them using the function you provide. The function takes two arguments: accumulator and current value. The accumulator stores the result as you go through the array. You can also provide an initial value. reduce is used when you want to combine all array elements into one value like sum, product, or object.

Question 10: Can you chain map, filter, and reduce?

Good Answer: Yes, you can chain map, filter, and reduce together. Each method returns an array or value so you can call the next method on it. For example, you can filter an array first, then map to transform it, then reduce to get a final value. Chaining makes code clean and readable.

Question 11: What happens if you do not provide initial value to reduce?

Good Answer: If you do not provide an initial value to reduce, it will use the first element of the array as the initial value and start reducing from the second element. However, it is better to always provide an initial value to avoid confusion and bugs, especially with empty arrays.

Question 12: What is the difference between map and forEach?

Good Answer: map returns a new array with transformed elements while forEach does not return anything. forEach just loops through the array and runs a function on each element. Use map when you want to transform an array. Use forEach when you just want to do something with each element without creating a new array.

On this page