<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Why Does JavaScript Feel So AbSuRd?]]></title><description><![CDATA[Why does [] == false? Why does 0.1 + 0.2 betray us? Explore JavaScript beyond syntax type coercion, numbers, functions, currying, composition, and the history behind its weirdest behaviors.]]></description><link>https://zaxx-blog.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 07 Sep 2026 15:28:18 GMT</lastBuildDate><atom:link href="https://zaxx-blog.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[Why Does JavaScript Feel So AbSuRd? Part - 3]]></title><description><![CDATA[let's continue gng !
Hoisting
What is hoisting really?
The beginner explanation usually says that JavaScript "moves declarations to the top". That is a useful first approximation, but technically it i]]></description><link>https://zaxx-blog.hashnode.dev/why-does-javascript-feel-so-absurd-part-3</link><guid isPermaLink="true">https://zaxx-blog.hashnode.dev/why-does-javascript-feel-so-absurd-part-3</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Rohit]]></dc:creator><pubDate>Mon, 07 Sep 2026 14:33:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9ac9e3e4e64ca9bd011135/fb20cdce-ee5d-4c55-85d2-a04602f770b7.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>let's continue gng !</p>
<h2>Hoisting</h2>
<h3>What is hoisting really?</h3>
<p>The beginner explanation usually says that JavaScript "moves declarations to the top". That is a useful first approximation, but technically it is too vague.<br />A better model is that JavaScript creates the execution environment before executing the code and registers declarations in their appropriate scope.<br />Different declarations are initialised differently.</p>
<pre><code class="language-javascript">console.log(hoistedVar);

var hoistedVar = 'value';
// undefined
</code></pre>
<p>The <code>var</code> binding exists and is initialised to <code>undefined</code> before the assignment executes.<br />With <code>let</code> and <code>const</code>, the binding exists but is not initialised until execution reaches the declaration.</p>
<pre><code class="language-javascript">console.log(hoistedLet);

let hoistedLet = 'value';
// ReferenceError
</code></pre>
<p>The period between entering the scope and reaching the declaration is called the Temporal Dead Zone, or TDZ.<br />Function declarations behave differently again.</p>
<pre><code class="language-javascript">hoistedFn();

function hoistedFn() {
  console.log('works!');
}
</code></pre>
<p>The function declaration is fully initialised before execution reaches the call.<br />A function expression does not work the same way.</p>
<pre><code class="language-javascript">hoistedExpr();

var hoistedExpr = function () {
};
</code></pre>
<p>The variable itself is initially <code>undefined</code>, so attempting to call it produces a <code>TypeError</code>.<br />Classes are also affected by the TDZ.</p>
<pre><code class="language-javascript">new MyClass();

class MyClass {
}
</code></pre>
<hr />
<h2>Closures</h2>
<h3>What is a closure?</h3>
<p>A closure is a function together with the lexical environment in which that function was created.<br />That definition sounds academic, but the behaviour is easier to see in code.</p>
<pre><code class="language-javascript">function makeCounter() {
  let count = 0;

  return {
    increment() {
      return ++count;
    },

    decrement() {
      return --count;
    },

    get value() {
      return count;
    },
  };
}

const counter = makeCounter();

counter.increment();
// 1

counter.increment();
// 2

counter.value;
// 2

counter.count;
// undefined
</code></pre>
<h3>How does debounce work?</h3>
<p>Debouncing means delaying an operation until activity has stopped for a specified amount of time.<br />This is extremely common in search inputs. If a user types <code>hello</code>, you usually do not want to send a network request for <code>h</code>, then <code>he</code>, then <code>hel</code>, then <code>hell</code>, and finally <code>hello</code>.</p>
<pre><code class="language-javascript">function debounce(fn, delay = 300) {
  let timeoutId;

  return function (...args) {
    clearTimeout(timeoutId);

    timeoutId = setTimeout(
      () =&gt; fn.apply(this, args),
      delay
    );
  };
}

const search = debounce(
  query =&gt; fetchResults(query),
  400
);

input.addEventListener(
  'input',
  e =&gt; search(e.target.value)
);
</code></pre>
<h3>Why does debounce use <code>fn.apply(this, args)</code>?</h3>
<p><code>apply()</code> invokes a function with a specified <code>this</code> value and an array of arguments.</p>
<pre><code class="language-javascript">function introduce(greeting, punctuation) {
  return `${greeting}, I am ${this.name}${punctuation}`;
}

const person = {
  name: 'Rohit'
};

introduce.apply(person, ['Hello', '!']);
// 'Hello, I am Rohit!'
</code></pre>
<p>In the debounce implementation, the wrapper function is deliberately a regular function.</p>
<pre><code class="language-javascript">return function (...args) {
  clearTimeout(timeoutId);

  timeoutId = setTimeout(
    () =&gt; fn.apply(this, args),
    delay
  );
};
</code></pre>
<hr />
<h3>What is throttling?</h3>
<p>Debouncing waits until activity stops. Throttling limits how frequently something can run.<br />A throttled function can be called many times, but the actual operation is restricted to a particular interval.</p>
<pre><code class="language-javascript">function throttle(fn, limit = 300) {
  let inThrottle = false;
  let lastArgs = null;

  return function (...args) {
    if (inThrottle) {
      lastArgs = args;
      return;
    }

    fn.apply(this, args);
    inThrottle = true;

    setTimeout(() =&gt; {
      inThrottle = false;

      if (lastArgs) {
        fn.apply(this, lastArgs);
        lastArgs = null;
      }
    }, limit);
  };
}
</code></pre>
<hr />
<h3>How does memoisation use closures?</h3>
<p>Memoisation means caching the result of a function so that repeated calls with the same inputs can reuse previously calculated results.</p>
<pre><code class="language-javascript">function memoize(fn) {
  const cache = new Map();

  return function (...args) {
    const key = JSON.stringify(args);

    if (cache.has(key)) {
      return cache.get(key);
    }

    const result = fn.apply(this, args);

    cache.set(key, result);

    return result;
  };
}
</code></pre>
<hr />
<h3>What does <code>once()</code> do?</h3>
<p><code>once()</code> creates a function that allows another function to execute only once.</p>
<pre><code class="language-javascript">function once(fn) {
  let called = false;
  let result;

  return function (...args) {
    if (called) {
      return result;
    }

    called = true;
    result = fn.apply(this, args);

    return result;
  };
}

const initialize = once(() =&gt; {
  console.log('init');
  return { ready: true };
});

initialize();
// logs and returns { ready: true }

initialize();
// no log, returns the cached object
</code></pre>
<hr />
<h2>Module Pattern</h2>
<h3>Can closures create private data?</h3>
<p>Yes. The classic module pattern is essentially a closure used to expose a controlled public API while keeping internal state private.</p>
<pre><code class="language-javascript">const UserStore = (function () {
  const users = new Map();
  let nextId = 1;

  function validate(user) {
    if (!user.email?.includes('@')) {
      throw new Error('Invalid email');
    }
  }

  return {
    add(user) {
      validate(user);

      const id = nextId++;

      users.set(id, {
        ...user,
        id
      });

      return id;
    },

    get(id) {
      return users.get(id);
    },

    get size() {
      return users.size;
    },
  };
})();

UserStore.add({
  email: 'a@b.com'
});

UserStore.users;
// undefined

UserStore.validate;
// undefined
</code></pre>
<hr />
<h3>What are the five main <code>this</code> rules?</h3>
<ol>
<li>new binding When a function is called with new, this refers to the newly created object.</li>
</ol>
<pre><code class="language-javascript">function Person(name) {
  this.name = name;
}

const person = new Person('Rohit');

console.log(person.name);
// 'Rohit'
</code></pre>
<ol>
<li>Explicit binding call(), apply(), and bind() allow you to explicitly control this.</li>
</ol>
<pre><code class="language-javascript">function greet() {
  return `Hi, ${this.name}`;
}

greet.call({
  name: 'Rohit'
});
// 'Hi, Rohit'

greet.apply(
  { name: 'Rohit' },
  []
);
// 'Hi, Rohit'

const bound = greet.bind({
  name: 'Rohit'
});

bound();
// 'Hi, Rohit'
</code></pre>
<p><code>call()</code> and <code>apply()</code> execute immediately. <code>bind()</code> creates a new function that remembers the chosen <code>this</code>.</p>
<p>3. Implicit binding When a function is called as an object method, the object before the dot becomes this.</p>
<pre><code class="language-javascript">const obj = {
  name: 'Rohit',

  greet() {
    return `Hi, ${this.name}`;
  }
};

obj.greet();
// 'Hi, Rohit'
</code></pre>
<p>The call site is what matters here. The function is being called as <code>obj.greet()</code>, so <code>this</code> is <code>obj</code>.</p>
<p>4. Default binding A plain function call does not provide an object for implicit binding.</p>
<pre><code class="language-javascript">function standalone() {
  return this;
}

standalone();
</code></pre>
<p>In strict mode and modules, <code>this</code> is <code>undefined</code>. In non-strict code, the default can be <code>globalThis</code>.</p>
<p>5. Arrow functions Arrow functions do not create their own this.</p>
<pre><code class="language-javascript">const arrow = () =&gt; this;

arrow.call({
  name: 'X'
});
</code></pre>
<hr />
<h3>Why does this disappear when I store a method in another variable?</h3>
<p>Consider this.</p>
<pre><code class="language-javascript">const user = {
  name: 'Rohit',

  greet() {
    return `Hi, ${this.name}`;
  },
};

user.greet();
// 'Hi, Rohit'

const fn = user.greet;

fn();
// 'Hi, undefined'
</code></pre>
<hr />
<h3>Why does <code>setTimeout(user.greet, 100)</code> lose <code>this</code>?</h3>
<p>Because you are passing the function itself to another piece of code.</p>
<pre><code class="language-javascript">setTimeout(user.greet, 100);
</code></pre>
<p>This effectively says, "Here is the function. Call it later."<br />The timer does not remember that you originally obtained the function from <code>user.greet</code>. The relationship between the function and the object is not stored inside the function.<br />Compare that with this.</p>
<pre><code class="language-javascript">setTimeout(() =&gt; user.greet(), 100);
</code></pre>
<hr />
<h3>How can we preserve <code>this</code>?</h3>
<p>One option is <code>bind()</code>.</p>
<pre><code class="language-javascript">setTimeout(
  user.greet.bind(user),
  100
);
</code></pre>
<p>Another option is to use a wrapper arrow function.</p>
<pre><code class="language-javascript">setTimeout(
  () =&gt; user.greet(),
  100
);
</code></pre>
<p>For class instances, a class-field arrow function is another option when you specifically need a method that survives detachment.</p>
<pre><code class="language-javascript">class User {
  name = 'Rohit';

  greet = () =&gt; `Hi, ${this.name}`;
}
</code></pre>
<p>The class-field arrow gets its lexical <code>this</code> from the instance initialization context. The trade-off is that each instance gets its own function rather than sharing one function on the prototype.</p>
<hr />
<h3>What is the difference between <code>call()</code>, <code>apply()</code>, and <code>bind()</code>?</h3>
<p>All three are related to controlling <code>this</code>, but they differ in when the function executes and how arguments are supplied.</p>
<pre><code class="language-javascript">function introduce(greeting, punctuation) {
  return `${greeting}, I am ${this.name}${punctuation}`;
}

const person = {
  name: 'Rohit'
};

introduce.call(
  person,
  'Hello',
  '!'
);
// 'Hello, I am Rohit!'

introduce.apply(
  person,
  ['Hello', '!']
);
// 'Hello, I am Rohit!'

const bound = introduce.bind(
  person,
  'Hello'
);

bound('!');
// 'Hello, I am Rohit!'
</code></pre>
<hr />
<h2>Method Borrowing</h2>
<h3>What is method borrowing?</h3>
<p>JavaScript methods are functions, so sometimes you can borrow a method from one object or prototype and call it with another object as its <code>this</code>.<br />For example, an array method can operate on an array-like object.</p>
<pre><code class="language-javascript">const arrayLike = {
  0: 'a',
  1: 'b',
  length: 2
};

Array.prototype.join.call(
  arrayLike,
  '-'
);
// 'a-b'
</code></pre>
<p>The object is not actually an Array, but it has the indexed properties and <code>length</code> that <code>join()</code> needs.<br />Modern JavaScript often provides cleaner alternatives.</p>
<pre><code class="language-javascript">Array.from(arrayLike);
// ['a', 'b']
</code></pre>
<p>Still, understanding method borrowing helps explain why <code>call()</code> and <code>apply()</code> are more than just interview trivia.</p>
<hr />
<h2>Putting It All Together</h2>
<h3>Why are closures, higher-order functions, <code>this</code>, scope, and <code>reduce()</code> all appearing in the same chapter?</h3>
<h3>What should I actually remember from this entire section?</h3>
<p>Build the mental model first.<br />Functions in JavaScript are values, which is why they can be stored, passed around, and returned. Higher-order functions take advantage of that ability to build reusable behaviour around other functions.<br />Regular functions and arrow functions are not interchangeable. Regular functions have dynamic <code>this</code>, their own <code>arguments</code>, and can be constructors. Arrow functions use lexical <code>this</code>, do not have their own <code>arguments</code>, and cannot be used with <code>new</code>.<br />Scope is lexical. JavaScript resolves variables by walking outward through the scope chain from where the code was written.<br />Hoisting is better understood as environment creation and declaration initialisation than as variables physically moving upward. <code>var</code> is initialised to <code>undefined</code>, while <code>let</code>, <code>const</code>, and classes remain uninitialised in the TDZ until execution reaches their declarations. Function declarations are fully initialised.<br />Closures happen when a function retains access to its lexical environment. That single mechanism powers private state, callbacks that remember context, debouncing, throttling, memoisation, currying, and the classic module pattern.<br /><code>reduce()</code> is not just a fancy way to add numbers. It is a general accumulation mechanism, and it becomes particularly interesting when the accumulated value is passed through a sequence of functions.<br />Composition combines functions from right to left, while <code>pipe()</code> usually expresses the same idea from left to right.<br />Finally, <code>this</code> for regular functions is determined by how the function is called. When you detach an object method, you detach the implicit receiver too. Arrow functions behave differently because their <code>this</code> is lexical.<br />Once these ideas click, a lot of JavaScript stops looking like a random collection of language quirks and starts looking like several features built on top of a few consistent mechanisms.<br />And yes, there will still be moments where JavaScript makes you stare at the screen for five minutes.<br />That part is apparently included in the runtime.</p>
<hr />
<h3>Answer to the question from Part 2</h3>
<p>We can finally answer the question we left hanging at the beginning.</p>
<pre><code class="language-javascript">const user = {
  name: 'Rohit',
  greet() {
    return `Hi, ${this.name}`;
  },
};

const fn = user.greet;

fn();
// 'Hi, undefined'

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

setTimeout(() =&gt; user.greet(), 100);
// works
</code></pre>
<p>The first call works differently from what you might expect because <code>this</code> is not permanently attached to the function when the function is defined. For a regular function, <code>this</code> is determined by the call site.</p>
<p>When we write <code>user.greet()</code>, the function is being called as a method of <code>user</code>, so the implicit binding rule gives <code>greet()</code> a <code>this</code> value of <code>user</code>. That is why <code>this.name</code> gives us <code>'Rohit'</code>.</p>
<p>But then we do this:</p>
<pre><code class="language-javascript">const fn = user.greet;
</code></pre>
<p>We have taken the function out of the object and stored it in another variable. The function itself is still the same function, but the call site has changed.</p>
<pre><code class="language-javascript">fn();
</code></pre>
<p>This is now a plain function call. There is no <code>user</code> before the dot, so there is no implicit binding to <code>user</code>. In strict mode, <code>this</code> is <code>undefined</code>. The important point is that the function did not forget <code>user</code>; it was never permanently bound to <code>user</code> in the first place.</p>
<p>The same thing happens here:</p>
<pre><code class="language-javascript">setTimeout(user.greet, 100);
</code></pre>
<p>We are passing the function itself to <code>setTimeout</code>. The timer receives a reference to the function, not an instruction saying "call this function as <code>user.greet()</code>". When the timer eventually invokes it, the original object relationship is gone.</p>
<p>Now look at the final example:</p>
<pre><code class="language-javascript">setTimeout(() =&gt; user.greet(), 100);
</code></pre>
<p>This time we are not passing <code>user.greet</code> directly. We are passing an arrow function that contains the expression <code>user.greet()</code>.</p>
<p>When the timer executes the arrow function, that expression is evaluated exactly as written. The call site once again contains <code>user</code>, so <code>greet()</code> receives <code>user</code> as its implicit <code>this</code>.</p>
<p>So the three cases are really three different call sites.</p>
<pre><code class="language-javascript">user.greet();
// `this` is user

const fn = user.greet;
fn();
// no implicit receiver

setTimeout(user.greet, 100);
// the function is passed around and called later

setTimeout(() =&gt; user.greet(), 100);
// the wrapper later performs `user.greet()`
</code></pre>
<p>And that is the answer we were looking for.</p>
<p>The function did not lose some magical connection to the object. JavaScript never stored that connection in the regular function in the first place. The value of <code>this</code> is determined when the function is called, and changing the way the function is called changes what <code>this</code> refers to.</p>
<p>So if you remember only one thing from this entire detour, remember this:</p>
<blockquote>
<p><strong>For regular functions,</strong> <code>this</code> <strong>comes from the call site, not from where the function was defined.</strong></p>
</blockquote>
<p>That one rule is responsible for a ridiculous amount of JavaScript confusion.</p>
<p>And finally, after all that, we can officially close the tab that Part 2 left open.</p>
]]></content:encoded></item><item><title><![CDATA[Why Does JavaScript Feel So AbSuRd?  Part - 2]]></title><description><![CDATA[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, occasi]]></description><link>https://zaxx-blog.hashnode.dev/why-does-javascript-feel-so-absurd-part-2</link><guid isPermaLink="true">https://zaxx-blog.hashnode.dev/why-does-javascript-feel-so-absurd-part-2</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><dc:creator><![CDATA[Rohit]]></dc:creator><pubDate>Sun, 06 Sep 2026 06:47:18 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9ac9e3e4e64ca9bd011135/8259dcba-8a3e-4c07-b34b-07357ce70a18.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>If <strong>Part 1</strong> was about JavaScript doing suspicious things with values and bullshit like that , <strong>Part 2</strong> is where we meet the thing that makes JavaScript feel like an actual programming language and, occasionally, like a homeless kid (orphan) !</p>
<p>Let's take an example.</p>
<pre><code class="language-javascript">const user = {
  name: 'Rohit',
  greet() {
    return `Hi, ${this.name}`;
  },
};

const fn = user.greet;

fn();
// 'Hi, undefined'

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

setTimeout(() =&gt; user.greet(), 100);
// works
</code></pre>
<p>Can you answer why the first two calls fail while the last one works? If you can, probably this blog is not for you.</p>
<p>But if you can't, then it's completely up to you whether you want to read this article or continue staring at <code>this</code> until it starts staring back.</p>
<p>The interesting part is that all three examples involve the same <em><strong>function</strong></em>.</p>
<p><em><strong>Functions</strong></em> 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.</p>
<p>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 <code>this</code> .</p>
<hr />
<h3>What exactly is a function in JavaScript?</h3>
<p>A function is a value that represents executable behaviour. That sounds simple, but the important part is the word value.</p>
<p>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.</p>
<p>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.</p>
<pre><code class="language-javascript">// Function expression
const subtract = function (a, b) {
  return a - b;
};

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

const square = x =&gt; x * x;

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

// Named function expression
const factorial = function fact(n) {
  return n &lt;= 1 ? 1 : n * fact(n - 1);
};
</code></pre>
<p>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 <code>this</code>, <code>arguments</code>, <code>constructors</code>, and <code>prototypes</code>.</p>
<p>JavaScript also has specialised forms such as async functions, generator functions, and async generators.</p>
<pre><code class="language-javascript">async function fetchData() {
}

function* idGenerator() {
  let i = 0;

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

async function* streamPages() {
}
</code></pre>
<p>So when someone says "a function is a function" screw them up , they don't know.</p>
<hr />
<h3>Why does the distinction between regular functions and arrow functions matter?</h3>
<p>Because an arrow function is not simply a shorter way of writing a regular function.</p>
<p>The biggest difference is this. A regular function gets its <code>this</code> value from the way it is called. An arrow function does not create its own <code>this</code>; it takes this from the surrounding lexical scope.</p>
<p>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.</p>
<pre><code class="language-javascript">const counter = {
  count: 0,

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

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

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

  start() {
    setInterval(() =&gt; {
      this.count++;
    }, 1000);
  },
};
</code></pre>
<p>The usual rule is simple enough to remember. If a function is an object or class method and needs the object's <code>this</code>, use a regular function. If you are writing a callback inside that method and want to keep the surrounding <code>this</code>, an arrow function is often exactly what you want.</p>
<hr />
<h3>What are default parameters?</h3>
<p>Default parameters allow a function to use a fallback value when the corresponding argument is undefined.</p>
<p>The default is evaluated when the function is called, not when the function is defined, and parameter defaults are evaluated from left to right.</p>
<pre><code class="language-javascript">function greet(name = 'Guest', greeting = `Hello, ${name}`) {
  return greeting;
}

greet();
// 'Hello, Guest'

greet('Rohit');
// 'Hello, Rohit'
</code></pre>
<p>One detail that catches people is that the default only applies to <code>undefined</code>, not to every falsy value and not to <code>null</code>.</p>
<pre><code class="language-javascript">function f(x = 5) {
  return x;
}

f(undefined);
// 5

f(null);
// null
</code></pre>
<p>So null basically says, "I intentionally gave you null." JavaScript respects that decision.</p>
<hr />
<h3>What are rest parameters?</h3>
<p>Rest parameters collect the remaining arguments into a real array.</p>
<pre><code class="language-javascript">function sum(...numbers) {
  return numbers.reduce((total, n) =&gt; total + n, 0);
}

sum(1, 2, 3, 4);
// 10
</code></pre>
<p>This is different from the older <code>arguments</code> object because rest parameters give you an actual array, so array methods can be used directly.</p>
<p>You can also combine a normal parameter with rest parameters.</p>
<pre><code class="language-javascript">function log(level, ...messages) {
  console[level](...messages);
}
</code></pre>
<p>Here level receives the first argument and messages collects everything after it.</p>
<hr />
<h3>Why do we sometimes write <code>= {}</code> in a destructured parameter?</h3>
<p>This pattern is common when a function accepts an options object.</p>
<pre><code class="language-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'
</code></pre>
<p>The final <code>= {}</code> is important because without it, calling <code>createServer()</code> would try to destructure <code>undefined</code>, which is not possible.</p>
<p>The inner defaults handle missing properties. The outer default handles the case where the entire argument is missing.</p>
<p>That tiny <code>= {}</code> is doing more work than it looks like.</p>
<hr />
<h2>First-Class Functions</h2>
<h3>What does it mean when people say "functions are first-class citizens"?</h3>
<p>It means functions can be treated like ordinary values.</p>
<p>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.</p>
<pre><code class="language-javascript">function add(a, b) {
  return a + b;
}

const operation = add;

operation(2, 3);
// 5
</code></pre>
<p>You can also pass a function into another function.</p>
<pre><code class="language-javascript">function execute(fn, value) {
  return fn(value);
}

execute(x =&gt; x * 2, 5);
// 10
</code></pre>
<p>And you can return a function.</p>
<pre><code class="language-javascript">function createMultiplier(multiplier) {
  return value =&gt; value * multiplier;
}

const double = createMultiplier(2);

double(5);
// 10
</code></pre>
<p>This ability to move functions around as values is one of the central ideas behind functional programming in JavaScript.</p>
<hr />
<h3>What is a higher order function?</h3>
<p>A higher-order function is a function that takes another function as an argument, returns a function, or does both.</p>
<p>For example, we can create a wrapper that adds logging around another function.</p>
<pre><code class="language-javascript">const withLogging = fn =&gt; (...args) =&gt; {
  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);
</code></pre>
<p><code>withLogging</code> is higher-order because it receives a function and returns another function.</p>
<p>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.</p>
<hr />
<h3>Why does <code>reduce()</code> matter so much?</h3>
<p><code>reduce()</code> takes a collection and repeatedly combines its elements into one accumulated result.</p>
<p>The accumulator is the key idea. On each iteration, the callback receives the result produced so far and the current element.</p>
<pre><code class="language-javascript">const numbers = [1, 2, 3, 4];

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

console.log(total);
// 10
</code></pre>
<p>The first accumulator value is <code>0</code>. JavaScript then processes the array one element at a time, carrying the previous result into the next iteration.</p>
<p>More importantly for functional programming, <code>reduce()</code> can be used to build a result by repeatedly applying functions. That idea leads directly to composition and <code>pipe()</code>.</p>
<hr />
<h3>What is currying?</h3>
<p>Currying transforms a function that normally accepts several arguments into a sequence of functions that each accept arguments progressively.</p>
<p>nstead of this:</p>
<pre><code class="language-javascript">add3(1, 2, 3);
</code></pre>
<p>you can have:</p>
<pre><code class="language-javascript">add3(1)(2)(3);
</code></pre>
<p>A simple curry implementation can be written like this.</p>
<pre><code class="language-javascript">const curry = fn =&gt;
  function curried(...args) {
    return args.length &gt;= fn.length
      ? fn(...args)
      : (...more) =&gt; curried(...args, ...more);
  };

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

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

add3(1, 2)(3);
// 6
</code></pre>
<p>The returned function remembers the arguments collected so far and waits until enough arguments have been provided.</p>
<p>This implementation depends on <code>fn.length</code>, which is the number of declared parameters before the first default or rest parameter.</p>
<pre><code class="language-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
</code></pre>
<p>That is why this simple curry implementation is useful for learning but should not be treated as a universal currying library.</p>
<hr />
<h2>Composition</h2>
<h3>What is function composition?</h3>
<p>Composition means combining small functions so that the output of one function becomes the input of another.</p>
<p>Suppose we have three transformations.</p>
<pre><code class="language-javascript">const trim = value =&gt; value.trim();

const lower = value =&gt; value.toLowerCase();

const removeSpaces = value =&gt;
  value.replace(/\s+/g, '-');
</code></pre>
<p>Instead of manually calling them one by one, we can create a new function that represents the entire operation.</p>
<pre><code class="language-javascript">const compose = (...fns) =&gt; x =&gt;
  fns.reduceRight(
    (acc, fn) =&gt; fn(acc),
    x
  );
</code></pre>
<p><code>compose()</code> applies functions from right to left.</p>
<pre><code class="language-javascript">const transform = compose(
  removeSpaces,
  lower,
  trim
);

transform('  Hello World  ');
// 'hello-world'
</code></pre>
<p>The value enters <code>trim</code>, then moves into <code>lower</code>, and finally reaches <code>removeSpaces</code>.</p>
<p>This style works particularly well when each function performs one small, predictable transformation.</p>
<hr />
<h3>Then what is <code>pipe()</code> ?</h3>
<p><code>pipe()</code> is essentially the left-to-right version of composition.</p>
<p>Instead of reading the functions from the right side backwards, you read them in the same order the data flows through them.</p>
<pre><code class="language-javascript">const pipe = (...fns) =&gt; x =&gt;
  fns.reduce(
    (acc, fn) =&gt; fn(acc),
    x
  );
</code></pre>
<p>Now we can build something that reads almost like a sequence of instructions.</p>
<pre><code class="language-javascript">const slugify = pipe(
  s =&gt; s.trim(),
  s =&gt; s.toLowerCase(),
  s =&gt; s.replace(/[^a-z0-9]+/g, '-'),
  s =&gt; s.replace(/^-|-$/g, '')
);

slugify('  Hello, World!  ');
// 'hello-world'
</code></pre>
<p>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.</p>
<hr />
<h3>What is scope?</h3>
<p>Scope determines where a variable can be accessed.</p>
<pre><code class="language-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();
}
</code></pre>
<p>The important difference is that <code>var</code> is function scoped, while <code>let</code> and <code>const</code> are block scoped.</p>
<pre><code class="language-javascript">function example() {
  if (true) {
    var a = 1;
    let b = 2;
  }

  console.log(a);
  // 1

  console.log(b);
  // ReferenceError
}
</code></pre>
<p>The braces create a block scope for <code>let</code> and <code>const</code>, but <code>var</code> ignores that block and belongs to the surrounding function scope.</p>
<hr />
<h3>What is the scope chain?</h3>
<p>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.</p>
<pre><code class="language-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();
</code></pre>
<p>When <code>level3()</code> looks for <code>a</code>, it does not find it locally, so JavaScript walks outward. It finds <code>a</code> in the global scope. The same process finds <code>b</code> in <code>level1</code> and <code>c</code> in <code>level2</code>.</p>
<p>This is called the scope chain.</p>
<p>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.</p>
<p>That rule is one of the reasons closures work.</p>
<hr />
<p>OHH !! I totally forgot to answer the question I asked at the very beginning of this discussion! 😭</p>
<p>But to get to that answer, we still have a long way to go and I think this is enough for this part.</p>
<p>To see the answer, you’ll have to wait for the next one.</p>
<p>See you in the next part!</p>
]]></content:encoded></item><item><title><![CDATA[Why Does JavaScript Feel So AbSuRd? Part - 1]]></title><description><![CDATA[Why Does JavaScript Feel So AbSuRd?
Try answering these all? [] == false // true 0.1 + 0.2 === 0.3 // false typeof null // "object" NaN === NaN // false 9007199254740992 === 9007199254740993 // true
D]]></description><link>https://zaxx-blog.hashnode.dev/why-does-javascript-feel-so-absurd-part-1</link><guid isPermaLink="true">https://zaxx-blog.hashnode.dev/why-does-javascript-feel-so-absurd-part-1</guid><category><![CDATA[JavaScript]]></category><category><![CDATA[Web Development]]></category><category><![CDATA[Programming Blogs]]></category><category><![CDATA[software development]]></category><dc:creator><![CDATA[Rohit]]></dc:creator><pubDate>Sat, 05 Sep 2026 05:17:56 GMT</pubDate><enclosure url="https://cdn.hashnode.com/uploads/covers/6a9ac9e3e4e64ca9bd011135/d468cadb-69e8-47db-ad13-4fc89b28ddd9.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3><strong>Why Does JavaScript Feel So AbSuRd?</strong></h3>
<p>Try answering these all? <code>[] == false</code> // true <code>0.1 + 0.2 === 0.3</code> // false <code>typeof null</code> // "object" <code>NaN === NaN</code> // false <code>9007199254740992 === 9007199254740993</code> // true</p>
<p>Did not get at least one right? Happens man! You, me, we both haven't spent enough time with JavaScript. Let's change that!</p>
<p>JavaScript has some wonderfully weird corners. Some of them are genuinely useful. Some are historical baggage. And some look completely ridiculous until you understand the rules underneath them.</p>
<p>But here's the interesting part: most of these behaviors are consequences of specific design decisions, type coercion rules, floating point representation, backward compatibility, and a language that has been evolving for decades while trying very hard not to break the web.</p>
<p><code>[] == false</code> is true. Why does JavaScript arrive at that answer? That's what this article is about.</p>
<p>This is Part 1 of my attempt to understand JavaScript beyond the syntax. We will start with numbers, then move into type coercion and operators, and try to understand why JavaScript behaves the way it does instead of simply memorizing a list of weird facts.</p>
<hr />
<h3><strong>Before We Start, JavaScript Has History</strong></h3>
<p>One of the easiest mistakes when learning JavaScript is assuming that it was designed as one perfectly planned language. It wasn't. Although JavaScript has evolved a lot, it also has a lot of history packed into it.</p>
<p>It started as a relatively small scripting language and eventually became the language running enormous parts of the web, including browsers, servers, build tools, applications, frameworks, extensions, tests, and much more.</p>
<p>And once millions of websites depend on a behavior, you can't simply just say:</p>
<blockquote>
<p>"Yeah, that was a terrible idea. Let's f*king remove it."</p>
</blockquote>
<p>Because somewhere out there is probably a website that depends on it.</p>
<p>This explains a lot of JavaScript's personality. Older ideas coexist with newer ones: • <code>var</code>, <code>let</code>, <code>const</code> • Old equality <code>==</code> vs Modern strict equality <code>===</code> • Prototype based objects <code>Object.create(...)</code> and later, class syntax <code>class User {}</code> • Callbacks <code>setTimeout(...)</code> and much later <code>async / await</code></p>
<p>JavaScript is less like a freshly designed building and more like a city. There are beautiful new buildings, ancient roads, strange shortcuts, and at least one intersection nobody knows how to remove because apparently somebody's production system depends on it.</p>
<p>And that's actually a useful way to learn JavaScript. Don't just ask what the syntax does. Ask why the language behaves that way.</p>
<hr />
<h3><strong>1. Numbers Are Not Quite What You Think</strong></h3>
<p>Let's start with something that looks completely innocent: <code>0.1 + 0.2</code>. You might expect <code>0.3</code>. JavaScript says <code>0.30000000000000004</code>. And <code>0.1 + 0.2 === 0.3</code> // false.</p>
<p>Let's understand what is happening. JavaScript's ordinary Number uses IEEE 754 double precision floating point representation. Computers don't store decimal numbers exactly the way humans write them.</p>
<p>We write <code>0.1</code>, <code>0.2</code>, <code>0.3</code>, but floating point numbers are represented using binary. And just like <code>1 / 3</code> cannot be represented exactly using a finite number of decimal digits (<code>0.333333333333...</code>), some decimal fractions cannot be represented exactly in binary.</p>
<p>So JavaScript stores the closest representable value. That means the values involved in <code>0.1 + 0.2</code> are already approximations. The result is therefore approximately <code>0.30000000000000004</code>.</p>
<p>This isn't uniquely a JavaScript problem. It's a consequence of floating point representation.</p>
<p><strong>Comparing Floating Point Numbers</strong> Because of this, directly comparing floating point values can be dangerous. Instead of blindly doing <code>a === b</code>, you can compare whether they're sufficiently close: <code>const nearlyEqual = (a, b, eps = Number.EPSILON) =&gt; Math.abs(a - b) &lt; eps;</code> <code>nearlyEqual(0.1 + 0.2, 0.3); // true</code></p>
<p>The exact comparison strategy should depend on the scale and requirements of your calculation, but the important idea is simple: floating point arithmetic is approximate.</p>
<hr />
<h3><strong>2. The Number Safe Integer Limit</strong></h3>
<p>JavaScript numbers have another interesting limitation: <code>Number.MAX_SAFE_INTEGER</code> gives <code>9007199254740991</code>, which is <code>2^53 - 1</code>.</p>
<p>Why can't JavaScript safely represent every integer beyond this? Because Number is a floating point format, and it has limited precision. Eventually, two different integers can round to the same representable floating point value.</p>
<p>For example: <code>9007199254740992 === 9007199254740993</code> // true.</p>
<p>That looks completely absurd. But the important word is precision here. The number isn't necessarily too large to exist. JavaScript simply can't represent every integer in that range distinctly using Number.</p>
<p>You can check whether an integer is safe: <code>Number.isSafeInteger(2 ** 53); // false</code></p>
<p>For integers requiring arbitrary precision, JavaScript provides BigInt: <code>const huge = 9007199254740993n;</code> Notice the <code>n</code>. It indicates that this is an integer value represented using BigInt rather than Number.</p>
<hr />
<p><strong>3. NaN Is... Special</strong></p>
<p>Now we reach one of JavaScript's favorite ways to confuse beginners like me: <code>NaN === NaN</code> // false. Wait whaaaaat! How can something not equal itself?</p>
<p>NaN represents a special numerical value that indicates an invalid or undefined numerical result. For example: <code>0 / 0</code> // NaN <code>Number("hello")</code> // NaN</p>
<p>NaN has special comparison semantics. So <code>NaN === NaN</code> // false. If you want to check whether something is actually NaN, use: <code>Number.isNaN(NaN)</code> // true</p>
<p>And notice the difference from the older global function: <code>isNaN("hello")</code> // true The global <code>isNaN()</code> performs coercion first. What the hell is coercion? We will come to that soon. <code>Number.isNaN()</code> does not: <code>Number.isNaN("hello")</code> // false It is generally much safer when you specifically want to know whether the value is the NaN value.</p>
<hr />
<h3><strong>4. Infinity Exists Too</strong></h3>
<p>JavaScript's number system also includes <code>Infinity</code>, <code>-Infinity</code>, and <code>NaN</code>. So: <code>1 / 0</code> // Infinity <code>-1 / 0</code> // -Infinity <code>0 / 0</code> // NaN</p>
<p>Again, these behaviors come from the floating point number model JavaScript uses.</p>
<hr />
<h3><strong>5. Never Blindly Use Floating Point for Money</strong></h3>
<p>A weird JavaScript behavior becomes a real engineering problem when money gets involved. Imagine calculating <code>0.1 + 0.2</code> once. Not a big deal. Now imagine doing floating point calculations across thousands of financial transactions. Suddenly tiny representation errors can become actual financial defects.</p>
<p>A common solution is to represent money using integer minor units. Instead of <code>₹19.99</code>, store <code>1999 paise</code>. Then arithmetic remains integer arithmetic and you divide by 100 only for display.</p>
<p>For calculations requiring decimal arithmetic, use an appropriate decimal representation or library and a suitable database type rather than blindly relying on binary floating point. A tiny floating point quirk can become a very non tiny production bug.</p>
<hr />
<h3><strong>6. Type Coercion, "I'll Figure It Out" Philosophy (lol)</strong></h3>
<p>Now let's talk about one of JavaScript's most famous features: type coercion. Here we go.</p>
<p>JavaScript can automatically convert values from one type to another depending on the operation being performed. For example: <code>1 == "1"</code> // true <code>1 === "1"</code> // false</p>
<p>What's happening? This is where JavaScript starts doing something that feels strange at first. The language can look at two values with different types and, depending on the operator, convert one or both values before comparing them. That automatic conversion is called type coercion.</p>
<hr />
<h3><strong>7.</strong> <code>==</code> <strong>vs</strong> <code>===</code></h3>
<p>The easiest way to think about them is: • <code>==</code> → allows type coercion • <code>===</code> → does not perform that coercion</p>
<p>So <code>1 == "1"</code> // true can involve converting the string <code>"1" → 1</code> and then comparing <code>1 == 1</code>. But <code>1 === "1"</code> // false because one value is a number and the other is a string.</p>
<p>This is why modern JavaScript code generally prefers <code>===</code> and <code>!==</code>. It makes the comparison more explicit and avoids many surprising conversions.</p>
<hr />
<h3><strong>8. The Famous null and undefined Case</strong></h3>
<p>Here's one of the few places where <code>==</code> can actually be useful: <code>null == undefined</code> // true But: <code>null === undefined</code> // false</p>
<p>They're different values, but loose equality has a special rule treating them as equivalent. So this: <code>value == null</code> can intentionally mean: "Is this either null or undefined?" Equivalent to: <code>value === null || value === undefined</code></p>
<p>This is one of the rare cases where using <code>==</code> can be intentional and readable. Everywhere else? I'd generally reach for <code>===</code>.</p>
<hr />
<h3><strong>9. And Then JavaScript Does This</strong></h3>
<p><code>[] == false</code> // true. At this point, JavaScript appears to have completely lost the plot. But let's slow down.</p>
<p>This isn't because an empty array is secretly false. In fact: <code>Boolean([])</code> // true. An empty array is truthy.</p>
<p>So why does <code>[] == false</code> produce true? Because <code>==</code> uses its own coercion rules. The object is converted toward a primitive value. Conceptually, the empty array can become: <code>[]</code> ↓ <code>""</code> ↓ <code>0</code> And <code>false</code> ↓ <code>0</code>. So the comparison eventually becomes <code>0 == 0</code>, which is <code>true</code>.</p>
<p>This is an important distinction. Equality coercion and boolean coercion are not the same thing. When JavaScript evaluates <code>if ([])</code>, it asks whether the value is truthy. Since an array is an object: <code>Boolean([])</code> // true.</p>
<p>But when evaluating <code>[] == false</code>, JavaScript follows the abstract equality algorithm, which involves different conversion rules. Same value. Different operation. Different rules. And that is a recurring theme in JavaScript.</p>
<hr />
<h3><strong>10. Truthy and Falsy</strong></h3>
<p>There are exactly eight falsy values: • <code>false</code>, <code>0</code>, <code>-0</code>, <code>0n</code>, <code>""</code>, <code>null</code>, <code>undefined</code>, <code>NaN</code></p>
<p>Everything else is truthy. That means these are all truthy: • <code>[]</code>, <code>{}</code>, <code>"0"</code>, <code>"false"</code>, <code>function () {}</code></p>
<p>Yes. Even <code>Boolean([])</code> // true and <code>Boolean({})</code> // true. Objects are truthy regardless of whether they're "empty." This is why: <code>if ([]) { // runs }</code></p>
<p>Understanding truthy and falsy values is important because JavaScript uses boolean conversion in many places, including <code>if</code>, <code>while</code>, logical operators, and conditional expressions.</p>
<hr />
<h3><strong>11. Explicit Conversion Is Usually Better</strong></h3>
<p>JavaScript can automatically convert values, but you can also explicitly convert them. And explicit conversion is usually easier to understand: <code>String(42)</code> // "42" <code>Number("42")</code> // 42 <code>Boolean(0)</code> // false</p>
<p>Some interesting examples: <code>Number("")</code> // 0 <code>Number(" 12 ")</code> // 12 <code>Number("12px")</code> // NaN</p>
<p>For parsing: <code>parseInt("12px", 10)</code> // 12 Notice the radix: <code>parseInt("12", 10)</code>. It's good practice to explicitly provide it. And <code>parseFloat("3.14em")</code> // 3.14.</p>
<p>JavaScript is willing to parse the numeric prefix here. That can be useful, but it can also be surprising if you expected strict validation.</p>
<p>The bigger lesson is that explicit conversion makes your intention visible. Instead of making the reader figure out what JavaScript might convert automatically, you can tell JavaScript exactly what type you want.</p>
<hr />
<h3><strong>12. Operators Have Their Own Personality</strong></h3>
<p>JavaScript operators don't always simply return booleans. Consider: <code>const name = input || "Anonymous";</code> The <code>||</code> operator returns one of its operands. It isn't simply true or false.</p>
<p>Similarly: <code>const port = process.env.PORT ?? 3000;</code> uses the nullish coalescing operator.</p>
<p>The difference between <code>||</code> and <code>??</code> is extremely important. Consider: <code>const count = 0;</code> <code>count || 10</code> // 10 (because 0 is falsy) <code>count ?? 10</code> // 0 (because ?? only falls back for null and undefined)</p>
<p>So: • <code>||</code> → fallback if falsy • <code>??</code> → fallback if null or undefined</p>
<p>If 0 is a legitimate value, <code>??</code> is often what you actually want.</p>
<p><strong>Logical Assignment</strong> JavaScript extends these ideas with logical assignment: <code>a ||= b;</code> <code>a &amp;&amp;= b;</code> <code>a ??= b;</code></p>
<p>Conceptually: • <code>a ||= b;</code> means roughly <code>a = a || b;</code> (Assign b if a is falsy) • <code>a &amp;&amp;= b;</code> means roughly <code>a = a &amp;&amp; b;</code> (Assign b if a is truthy) • <code>a ??= b;</code> means roughly <code>a = a ?? b;</code> (Assign b only if a is null or undefined)</p>
<p>These operators are small, but they become extremely useful once you understand the underlying behavior.</p>
<hr />
<p><strong>Where We Stop for Part 1</strong></p>
<p>So far, we've looked at the part of JavaScript that makes many people wonder whether the language was designed during a very long coffee break.</p>
<p>We've seen floating point precision, safe integers, NaN, Infinity, type coercion, loose and strict equality, truthy and falsy values, explicit conversion, nullish coalescing, and logical assignment.</p>
<p>But there is a much more interesting part of JavaScript waiting ahead: functions. Not just how to declare them, but why JavaScript treating functions as values changes almost everything.</p>
<p>In the next part, we'll get into first class functions, higher order functions, <code>reduce()</code>, closures, currying, function composition, <code>pipe()</code>, arrow functions, <code>this</code>, destructured parameters, and more.</p>
<p>And that's where JavaScript starts becoming less about syntax and more about how the language actually thinks.</p>
<p>See you in Part 2.</p>
]]></content:encoded></item></channel></rss>