# Why Does JavaScript Feel So AbSuRd?  Part - 2

If **Part 1** was about JavaScript doing suspicious things with values and bullshit like that , **Part 2** is where we meet the thing that makes JavaScript feel like an actual programming language and, occasionally, like a homeless kid (orphan) !

Let's take an example.

```javascript
const user = {
  name: 'Rohit',
  greet() {
    return `Hi, ${this.name}`;
  },
};

const fn = user.greet;

fn();
// 'Hi, undefined'

setTimeout(user.greet, 100);
// same problem

setTimeout(() => user.greet(), 100);
// works
```

Can you answer why the first two calls fail while the last one works? If you can, probably this blog is not for you.

But if you can't, then it's completely up to you whether you want to read this article or continue staring at `this` until it starts staring back.

The interesting part is that all three examples involve the same ***function***.

***Functions*** are everywhere in JavaScript. They can be stored in variables, passed to other functions, returned from functions, attached to objects, blah blah blah. Once you understand that functions are values and that JavaScript keeps track of the environment around those functions, a lot of features that initially look unrelated start fitting together.

This part follows that idea from the ground up. We will move through function forms, parameters, first class functions, higher order functions, reduce(), currying, composition, pipe(), scope, hoisting, closures, practical closure patterns, and finally the infamous `this` .

* * *

### What exactly is a function in JavaScript?

A function is a value that represents executable behaviour. That sounds simple, but the important part is the word value.

Because functions are values, you can assign them to variables, store them in objects or arrays, pass them as arguments, and return them from other functions. This is the foundation for higher-order functions, callbacks, composition, currying, and a huge amount of modern JavaScript.

A function can be written in several forms, and the form you choose can change things such as hoisting, this, constructor behaviour, and whether the function has its own arguments object.

```javascript
// Function expression
const subtract = function (a, b) {
  return a - b;
};

// Arrow function
const multiply = (a, b) => a * b;

const square = x => x * x;

// Function declaration
function add(a, b) {
  return a + b;
}

// Named function expression
const factorial = function fact(n) {
  return n <= 1 ? 1 : n * fact(n - 1);
};
```

The important distinction is that a function declaration is fully hoisted, while a function expression is created as part of the assignment. Arrow functions are also function expressions and have different behaviour around `this`, `arguments`, `constructors`, and `prototypes`.

JavaScript also has specialised forms such as async functions, generator functions, and async generators.

```javascript
async function fetchData() {
}

function* idGenerator() {
  let i = 0;

  while (true) {
    yield i++;
  }
}

async function* streamPages() {
}
```

So when someone says "a function is a function" screw them up , they don't know.

* * *

### Why does the distinction between regular functions and arrow functions matter?

Because an arrow function is not simply a shorter way of writing a regular function.

The biggest difference is this. A regular function gets its `this` value from the way it is called. An arrow function does not create its own `this`; it takes this from the surrounding lexical scope.

Regular functions also have their own arguments object and can be used with new. Arrow functions cannot be constructors and do not have their own arguments.

```javascript
const counter = {
  count: 0,

  // Wrong if you expect `this` to mean counter
  incrementBad: () => {
    this.count++;
  },

  // Correct
  increment() {
    this.count++;
  },

  startBad() {
    setInterval(function () {
      this.count++;
    }, 1000);
  },

  start() {
    setInterval(() => {
      this.count++;
    }, 1000);
  },
};
```

The usual rule is simple enough to remember. If a function is an object or class method and needs the object's `this`, use a regular function. If you are writing a callback inside that method and want to keep the surrounding `this`, an arrow function is often exactly what you want.

* * *

### What are default parameters?

Default parameters allow a function to use a fallback value when the corresponding argument is undefined.

The default is evaluated when the function is called, not when the function is defined, and parameter defaults are evaluated from left to right.

```javascript
function greet(name = 'Guest', greeting = `Hello, ${name}`) {
  return greeting;
}

greet();
// 'Hello, Guest'

greet('Rohit');
// 'Hello, Rohit'
```

One detail that catches people is that the default only applies to `undefined`, not to every falsy value and not to `null`.

```javascript
function f(x = 5) {
  return x;
}

f(undefined);
// 5

f(null);
// null
```

So null basically says, "I intentionally gave you null." JavaScript respects that decision.

* * *

### What are rest parameters?

Rest parameters collect the remaining arguments into a real array.

```javascript
function sum(...numbers) {
  return numbers.reduce((total, n) => total + n, 0);
}

sum(1, 2, 3, 4);
// 10
```

This is different from the older `arguments` object because rest parameters give you an actual array, so array methods can be used directly.

You can also combine a normal parameter with rest parameters.

```javascript
function log(level, ...messages) {
  console[level](...messages);
}
```

Here level receives the first argument and messages collects everything after it.

* * *

### Why do we sometimes write `= {}` in a destructured parameter?

This pattern is common when a function accepts an options object.

```javascript
function createServer({
  port = 3000,
  host = 'localhost',
  secure = false
} = {}) {
  return `${secure ? 'https' : 'http'}://${host}:${port}`;
}

createServer();
// 'http://localhost:3000'

createServer({ port: 8080 });
// 'http://localhost:8080'
```

The final `= {}` is important because without it, calling `createServer()` would try to destructure `undefined`, which is not possible.

The inner defaults handle missing properties. The outer default handles the case where the entire argument is missing.

That tiny `= {}` is doing more work than it looks like.

* * *

## First-Class Functions

### What does it mean when people say "functions are first-class citizens"?

It means functions can be treated like ordinary values.

You can assign a function to a variable, pass it to another function, return it from a function, or store it inside a data structure.

```javascript
function add(a, b) {
  return a + b;
}

const operation = add;

operation(2, 3);
// 5
```

You can also pass a function into another function.

```javascript
function execute(fn, value) {
  return fn(value);
}

execute(x => x * 2, 5);
// 10
```

And you can return a function.

```javascript
function createMultiplier(multiplier) {
  return value => value * multiplier;
}

const double = createMultiplier(2);

double(5);
// 10
```

This ability to move functions around as values is one of the central ideas behind functional programming in JavaScript.

* * *

### What is a higher order function?

A higher-order function is a function that takes another function as an argument, returns a function, or does both.

For example, we can create a wrapper that adds logging around another function.

```javascript
const withLogging = fn => (...args) => {
  console.log(`calling ${fn.name} with`, args);

  const result = fn(...args);

  console.log(`${fn.name} returned`, result);

  return result;
};

const loggedAdd = withLogging(add);

loggedAdd(2, 3);
```

`withLogging` is higher-order because it receives a function and returns another function.

This pattern is extremely useful because you can add behaviour without modifying the original function. Logging, authentication checks, caching, timing, retry logic, debouncing, throttling, and many other patterns can be built this way.A higher order function is a function that takes another function as an argument, returns a function, or does both.

* * *

### Why does `reduce()` matter so much?

`reduce()` takes a collection and repeatedly combines its elements into one accumulated result.

The accumulator is the key idea. On each iteration, the callback receives the result produced so far and the current element.

```javascript
const numbers = [1, 2, 3, 4];

const total = numbers.reduce(
  (accumulator, number) => accumulator + number,
  0
);

console.log(total);
// 10
```

The first accumulator value is `0`. JavaScript then processes the array one element at a time, carrying the previous result into the next iteration.

More importantly for functional programming, `reduce()` can be used to build a result by repeatedly applying functions. That idea leads directly to composition and `pipe()`.

* * *

### What is currying?

Currying transforms a function that normally accepts several arguments into a sequence of functions that each accept arguments progressively.

nstead of this:

```javascript
add3(1, 2, 3);
```

you can have:

```javascript
add3(1)(2)(3);
```

A simple curry implementation can be written like this.

```javascript
const curry = fn =>
  function curried(...args) {
    return args.length >= fn.length
      ? fn(...args)
      : (...more) => curried(...args, ...more);
  };

const add3 = curry((a, b, c) => a + b + c);

add3(1)(2)(3);
// 6

add3(1, 2)(3);
// 6
```

The returned function remembers the arguments collected so far and waits until enough arguments have been provided.

This implementation depends on `fn.length`, which is the number of declared parameters before the first default or rest parameter.

```javascript
function add(a, b, c) {
}

console.log(add.length);
// 3

function another(a, b = 10, c) {
}

console.log(another.length);
// 1

function many(a, ...numbers) {
}

console.log(many.length);
// 1
```

That is why this simple curry implementation is useful for learning but should not be treated as a universal currying library.

* * *

## Composition

### What is function composition?

Composition means combining small functions so that the output of one function becomes the input of another.

Suppose we have three transformations.

```javascript
const trim = value => value.trim();

const lower = value => value.toLowerCase();

const removeSpaces = value =>
  value.replace(/\s+/g, '-');
```

Instead of manually calling them one by one, we can create a new function that represents the entire operation.

```javascript
const compose = (...fns) => x =>
  fns.reduceRight(
    (acc, fn) => fn(acc),
    x
  );
```

`compose()` applies functions from right to left.

```javascript
const transform = compose(
  removeSpaces,
  lower,
  trim
);

transform('  Hello World  ');
// 'hello-world'
```

The value enters `trim`, then moves into `lower`, and finally reaches `removeSpaces`.

This style works particularly well when each function performs one small, predictable transformation.

* * *

### Then what is `pipe()` ?

`pipe()` is essentially the left-to-right version of composition.

Instead of reading the functions from the right side backwards, you read them in the same order the data flows through them.

```javascript
const pipe = (...fns) => x =>
  fns.reduce(
    (acc, fn) => fn(acc),
    x
  );
```

Now we can build something that reads almost like a sequence of instructions.

```javascript
const slugify = pipe(
  s => s.trim(),
  s => s.toLowerCase(),
  s => s.replace(/[^a-z0-9]+/g, '-'),
  s => s.replace(/^-|-$/g, '')
);

slugify('  Hello, World!  ');
// 'hello-world'
```

This is one of the places where reduce() becomes much more interesting. The accumulator is not necessarily a number. It can be the value moving through a chain of transformations.

* * *

### What is scope?

Scope determines where a variable can be accessed.

```javascript
const globalVar = 'global';

function outer() {
  const functionVar = 'function';

  if (true) {
    let blockVar = 'block';
    console.log(blockVar);
  }

  var functionScoped = 'also function';

  console.log(functionScoped);

  function inner() {
    console.log(globalVar, functionVar);
  }

  inner();
}
```

The important difference is that `var` is function scoped, while `let` and `const` are block scoped.

```javascript
function example() {
  if (true) {
    var a = 1;
    let b = 2;
  }

  console.log(a);
  // 1

  console.log(b);
  // ReferenceError
}
```

The braces create a block scope for `let` and `const`, but `var` ignores that block and belongs to the surrounding function scope.

* * *

### What is the scope chain?

When JavaScript encounters a variable reference, it looks for that variable in the current lexical environment. If it is not there, it moves outward through the enclosing scopes until it reaches the global scope.

```javascript
const a = 'global a';

function level1() {
  const b = 'level1 b';

  function level2() {
    const c = 'level2 c';

    function level3() {
      console.log(a, b, c);
    }

    level3();
  }

  level2();
}

level1();
```

When `level3()` looks for `a`, it does not find it locally, so JavaScript walks outward. It finds `a` in the global scope. The same process finds `b` in `level1` and `c` in `level2`.

This is called the scope chain.

The critical point is that scope is lexical. It is determined by where the code is written, not by where the function happens to be called from.

That rule is one of the reasons closures work.

* * *

OHH !! I totally forgot to answer the question I asked at the very beginning of this discussion! 😭

But to get to that answer, we still have a long way to go and I think this is enough for this part.

To see the answer, you’ll have to wait for the next one.

See you in the next part!
