{"id":4884,"date":"2026-09-17T00:18:07","date_gmt":"2026-09-16T18:48:07","guid":{"rendered":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/"},"modified":"2026-09-17T00:18:07","modified_gmt":"2026-09-16T18:48:07","slug":"best-way-to-learn-javascript-a-step-by-step-guide","status":"publish","type":"post","link":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/","title":{"rendered":"Best Way to Learn JavaScript: A Step-by-Step Guide"},"content":{"rendered":"<p>text<br \/>\n<SYSTEM_LOG_ENTRY: 2024-05-14T03:14:07.821Z><br \/>\nFATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed &#8211; JavaScript heap out of memory<br \/>\n 1: 0x101304560 node::Abort() [\/usr\/local\/bin\/node]<br \/>\n 2: 0x10130578c node::OnFatalError(char const<em>, char const<\/em>) [\/usr\/local\/bin\/node]<br \/>\n 3: 0x1014a8340 v8::Utils::ReportOOMFailure(v8::internal::Isolate<em>, char const<\/em>, bool) [\/usr\/local\/bin\/node]<br \/>\n 4: 0x1014a82d8 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate<em>, char const<\/em>, bool) [\/usr\/local\/bin\/node]<br \/>\n 5: 0x101645e90 v8::internal::Heap::FatalProcessOutOfMemory(char const<em>) [\/usr\/local\/bin\/node]<br \/>\n 6: 0x101647464 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [\/usr\/local\/bin\/node]<br \/>\n 7: 0x101643d1c v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [\/usr\/local\/bin\/node]<br \/>\n 8: 0x1016415a0 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) [\/usr\/local\/bin\/node]<br \/>\n 9: 0x101633e30 v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [\/usr\/local\/bin\/node]<br \/>\n10: 0x1016346bc v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) [\/usr\/local\/bin\/node]<br \/>\n11: 0x1016160d4 v8::internal::Factory::NewFillerObject(int, v8::internal::AllocationAlignment, v8::internal::AllocationType, v8::internal::AllocationOrigin) [\/usr\/local\/bin\/node]<br \/>\n12: 0x1019d1260 v8::internal::Runtime_AllocateInYoungGeneration(int, v8::internal::FullGuidance, v8::internal::Isolate<\/em>) [\/usr\/local\/bin\/node]<br \/>\n13: 0x101d6435c Builtins_CEntry_Return1_ArgvOnStack_NoBuiltinExit [\/usr\/local\/bin\/node]<\/p>\n<hr \/>\n<p>Node.js v20.10.0<br \/>\nV8 Engine v11.8.172.17-node.12<br \/>\nPlatform: linux x64<br \/>\nMemory Usage: RSS 4.2GB, Heap Total 3.8GB, Heap Used 3.75GB<\/p>\n<pre class=\"codehilite\"><code>### THE BODY COUNT: THE COST OF ABSTRACTION WITHOUT UNDERSTANDING\n\nFifty million dollars. That is the price tag of the &quot;move fast and break things&quot; ethos when applied to a migration involving three million concurrent users and a team of developers who think JavaScript is &quot;just C with curly braces and no types.&quot; We didn't fail because of a cloud provider outage. We didn't fail because of a cyberattack. We failed because our engineering staff\u2014most of whom were hired from six-month bootcamps where they were taught how to build a Todo list in React\u2014didn't understand how the Node.js event loop actually schedules tasks.\n\nThe body count is as follows:\n- **14,000 man-hours** spent rewriting a microservices architecture that was fundamentally sound but implemented by people who didn't know the difference between the stack and the heap.\n- **$12 million** in lost revenue during the 48-hour &quot;Black Friday&quot; outage caused by a single unhandled promise rejection that spiraled into a global process crash.\n- **4.2 GB of RAM** leaked every six minutes because someone thought it was a good idea to store user session data in a global object &quot;for speed.&quot;\n- **One senior architect** (me) who is currently drinking lukewarm coffee and wondering why we stopped teaching people how computers actually work.\n\nIf you want to survive in this industry, you need to stop &quot;learning&quot; JavaScript through 10-minute YouTube tutorials. You need to master it. The **best way** to achieve this is to strip away the frameworks and look at the engine.\n\n### THE FALLACY OF THE &quot;FRAMEWORK-FIRST&quot; MENTALITY\n\nThe industry has a sickness. We hire &quot;React Developers&quot; or &quot;Vue Developers&quot; instead of Software Engineers. When you start with a framework, you are learning a DSL (Domain Specific Language) built on top of a foundation you don't understand. It\u2019s like trying to be a structural engineer because you\u2019re good at playing with LEGOs.\n\nIn our failed migration, the &quot;Lead Frontend Engineer&quot; decided to implement a file-processing service using Node.js v20.10.0. Here is the first iteration of the code I found in the repository, which I have dubbed &quot;The Career Killer&quot;:\n\n```javascript\n\/\/ Version 1: The &quot;I learned this on a <a href=\"https:\/\/itsupportwale.com\/blog\/\" title=\"Read more about blog\">blog<\/a>&quot; approach\nconst fs = require('fs');\n\nfunction processConfig(path) {\n    const data = fs.readFileSync(path, 'utf8'); \/\/ BLOCKING THE EVENT LOOP\n    const config = JSON.parse(data);\n    return config;\n}\n\n\/\/ Used inside an Express route\napp.get('\/config', (req, res) =&gt; {\n    const config = processConfig('.\/large-config.json');\n    res.send(config);\n});\n<\/code><\/pre>\n<p>This looks innocent to a junior. It works on their local machine with a 2KB config file. But in production, with a 50MB JSON file and 5,000 concurrent requests, <code>fs.readFileSync<\/code> blocks the entire thread. The event loop stops. No other requests can be handled. The health check fails. Kubernetes kills the pod. The pod restarts, hits the same code, and dies again. This is a self-inflicted Distributed Denial of Service (DDoS) attack.<\/p>\n<p>The <strong>best way<\/strong> to avoid this is to understand that Node.js is single-threaded for your code, but multi-threaded for I\/O via libuv. If you block that single thread, you are dead.<\/p>\n<div id=\"ez-toc-container\" class=\"ez-toc-v2_0_80 counter-hierarchy ez-toc-counter ez-toc-grey ez-toc-container-direction\">\n<p class=\"ez-toc-title\" style=\"cursor:inherit\">Table of Contents<\/p>\n<label for=\"ez-toc-cssicon-toggle-item-6aac11fa3a54d\" class=\"ez-toc-cssicon-toggle-label\"><span class=\"\"><span class=\"eztoc-hide\" style=\"display:none;\">Toggle<\/span><span class=\"ez-toc-icon-toggle-span\"><svg style=\"fill: #999;color:#999\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" class=\"list-377408\" width=\"20px\" height=\"20px\" viewBox=\"0 0 24 24\" fill=\"none\"><path d=\"M6 6H4v2h2V6zm14 0H8v2h12V6zM4 11h2v2H4v-2zm16 0H8v2h12v-2zM4 16h2v2H4v-2zm16 0H8v2h12v-2z\" fill=\"currentColor\"><\/path><\/svg><svg style=\"fill: #999;color:#999\" class=\"arrow-unsorted-368013\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" width=\"10px\" height=\"10px\" viewBox=\"0 0 24 24\" version=\"1.2\" baseProfile=\"tiny\"><path d=\"M18.2 9.3l-6.2-6.3-6.2 6.3c-.2.2-.3.4-.3.7s.1.5.3.7c.2.2.4.3.7.3h11c.3 0 .5-.1.7-.3.2-.2.3-.5.3-.7s-.1-.5-.3-.7zM5.8 14.7l6.2 6.3 6.2-6.3c.2-.2.3-.5.3-.7s-.1-.5-.3-.7c-.2-.2-.4-.3-.7-.3h-11c-.3 0-.5.1-.7.3-.2.2-.3.5-.3.7s.1.5.3.7z\"\/><\/svg><\/span><\/span><\/label><input type=\"checkbox\"  id=\"ez-toc-cssicon-toggle-item-6aac11fa3a54d\"  aria-label=\"Toggle\" \/><nav><ul class='ez-toc-list ez-toc-list-level-1 ' ><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-1\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#MEMORY_LEAK_ANALYSIS_WHY_YOUR_PROMISES_ARE_EMPTY\" >MEMORY LEAK ANALYSIS: WHY YOUR PROMISES ARE EMPTY<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-2\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#V8_INTERNALS_AND_THE_MYTH_OF_%E2%80%9CMAGIC%E2%80%9D_OPTIMIZATION\" >V8 INTERNALS AND THE MYTH OF &#8220;MAGIC&#8221; OPTIMIZATION<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-3\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#THE_PROTOTYPE_CHAIN_NOT_A_HISTORY_LESSON_A_PERFORMANCE_REQUIREMENT\" >THE PROTOTYPE CHAIN: NOT A HISTORY LESSON, A PERFORMANCE REQUIREMENT<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-4\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#EXECUTION_CONTEXTS_AND_THE_%E2%80%9CTHIS%E2%80%9D_BINDING_DISASTER\" >EXECUTION CONTEXTS AND THE &#8220;THIS&#8221; BINDING DISASTER<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-5\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#THE_EVOLUTION_OF_ASYNCHRONOUS_IO_THE_%E2%80%9CBEST_WAY%E2%80%9D\" >THE EVOLUTION OF ASYNCHRONOUS I\/O: THE &#8220;BEST WAY&#8221;<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-6\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#THE_EVENT_LOOP_MACROTASKS_VS_MICROTASKS\" >THE EVENT LOOP: MACROTASKS VS. MICROTASKS<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-7\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#THE_ANATOMY_OF_A_STACK_OVERFLOW\" >THE ANATOMY OF A STACK OVERFLOW<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-8\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#THE_HIDDEN_COST_OF_NPM_INSTALL\" >THE HIDDEN COST OF NPM INSTALL<\/a><\/li><li class='ez-toc-page-1 ez-toc-heading-level-3'><a class=\"ez-toc-link ez-toc-heading-9\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#THE_%E2%80%9CBEST_WAY%E2%80%9D_TO_MASTERY_A_MANDATORY_READING_LIST\" >THE &#8220;BEST WAY&#8221; TO MASTERY: A MANDATORY READING LIST<\/a><\/li><\/ul><\/nav><\/div>\n<h3><span class=\"ez-toc-section\" id=\"MEMORY_LEAK_ANALYSIS_WHY_YOUR_PROMISES_ARE_EMPTY\"><\/span>MEMORY LEAK ANALYSIS: WHY YOUR PROMISES ARE EMPTY<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>We saw the <code>FATAL ERROR: Ineffective mark-compacts<\/code> log above. That wasn&#8217;t a fluke. It was the result of a fundamental misunderstanding of how the V8 Garbage Collector (GC) works. V8 uses a generational GC. Objects are allocated in the &#8220;New Space&#8221; (Young Generation). If they survive a couple of GC cycles, they are promoted to the &#8220;Old Space.&#8221;<\/p>\n<p>The juniors were creating &#8220;Dangling Promises.&#8221; They were initiating asynchronous operations without properly attaching <code>.catch()<\/code> handlers or using <code>await<\/code> within a <code>try\/catch<\/code> block. In Node.js v20, an unhandled rejection will eventually crash the process, but before it does, it can leave references hanging in the heap.<\/p>\n<p>Look at this evolution of our broken <code>fs.readFile<\/code> logic. The junior &#8220;fixed&#8221; the blocking issue by making it asynchronous, but they did it in the most memory-intensive way possible:<\/p>\n<pre class=\"codehilite\"><code class=\"language-javascript\">\/\/ Version 2: The &quot;I know what a Promise is&quot; approach\nconst fs = require('fs').promises;\n\nasync function processConfig(path) {\n    try {\n        \/\/ This reads the ENTIRE file into memory as a string\n        const data = await fs.readFile(path, 'utf8'); \n        const config = JSON.parse(data);\n        return config;\n    } catch (err) {\n        console.error(err);\n    }\n}\n<\/code><\/pre>\n<p>While this doesn&#8217;t block the event loop, it\u2019s a memory bomb. If 1,000 users hit this endpoint simultaneously, and the file is 50MB, you just allocated 50GB of strings in the heap. V8\u2019s heap limit is typically 4GB on a 64-bit system. The GC starts thrashing, trying to find space, and eventually, the process throws the OOM (Out of Memory) error you saw in the logs.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"V8_INTERNALS_AND_THE_MYTH_OF_%E2%80%9CMAGIC%E2%80%9D_OPTIMIZATION\"><\/span>V8 INTERNALS AND THE MYTH OF &#8220;MAGIC&#8221; OPTIMIZATION<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>You cannot write high-performance JavaScript without understanding the V8 pipeline. When your code runs, it is first parsed into an Abstract Syntax Tree (AST). Then, the <strong>Ignition<\/strong> interpreter generates bytecode. As the code runs, the <strong>TurboFan<\/strong> optimizing compiler watches for &#8220;hot&#8221; functions and compiles them into highly optimized machine code.<\/p>\n<p>However, TurboFan relies on &#8220;Hidden Classes&#8221; (also known as Shapes). If you change the structure of an object after it has been created, you &#8220;de-optimize&#8221; the function.<\/p>\n<pre class=\"codehilite\"><code class=\"language-javascript\">function User(name) {\n    this.name = name;\n}\n\nconst u1 = new User('Alice');\nconst u2 = new User('Bob');\n\n\/\/ These two objects share the same Hidden Class. TurboFan is happy.\n\nu2.age = 30; \n\n\/\/ Now u2 has a different Hidden Class. \n\/\/ Any function taking 'User' objects as arguments now has to deal with \n\/\/ polymorphic input, slowing down the execution.\n<\/code><\/pre>\n<p>In our migration, we had a &#8220;utility&#8221; function that merged objects using a dynamic loop. It was so polymorphic that TurboFan gave up and dropped back to the Ignition interpreter for the most critical path of our data processing. We saw a 400% CPU spike because the developers didn&#8217;t understand that the <strong>best way<\/strong> to write fast JS is to keep your object shapes stable. Initialize all your fields in the constructor, even if they are <code>null<\/code>.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"THE_PROTOTYPE_CHAIN_NOT_A_HISTORY_LESSON_A_PERFORMANCE_REQUIREMENT\"><\/span>THE PROTOTYPE CHAIN: NOT A HISTORY LESSON, A PERFORMANCE REQUIREMENT<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>I am tired of hearing that &#8220;classes in JS are just syntax sugar.&#8221; While true, it\u2019s a dangerous oversimplification. Understanding the prototype chain is essential for memory management. <\/p>\n<p>During the post-mortem, we found a piece of code where a developer was defining methods inside a constructor function:<\/p>\n<pre class=\"codehilite\"><code class=\"language-javascript\">function DataProcessor() {\n    this.process = function(data) {\n        \/\/ complex logic\n    };\n}\n<\/code><\/pre>\n<p>Every time <code>new DataProcessor()<\/code> was called, a new function object was created in memory. With 100,000 instances, that\u2019s 100,000 identical functions clogging the heap. If they had used the prototype (or the <code>class<\/code> syntax, which handles this correctly), there would be exactly one function in memory, shared across all instances.<\/p>\n<p>The <strong>best way<\/strong> to master this is to stop using <code>class<\/code> as a black box. You need to be able to explain how <code>Object.getPrototypeOf()<\/code> works and why <code>__proto__<\/code> is deprecated but still relevant to understanding the internal linkage of objects. If you can&#8217;t explain the difference between a function&#8217;s <code>prototype<\/code> property and an object&#8217;s <code>[[Prototype]]<\/code> internal slot, you shouldn&#8217;t be touching an enterprise codebase.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"EXECUTION_CONTEXTS_AND_THE_%E2%80%9CTHIS%E2%80%9D_BINDING_DISASTER\"><\/span>EXECUTION CONTEXTS AND THE &#8220;THIS&#8221; BINDING DISASTER<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>The <code>$50 million<\/code> failure reached its climax when our payment processing module failed because of a <code>this<\/code> binding error. A junior developer passed a class method as a callback to a third-party library without binding the context.<\/p>\n<pre class=\"codehilite\"><code class=\"language-javascript\">class PaymentGateway {\n    constructor() {\n        this.apiKey = 'secret_key';\n    }\n\n    handleResponse(res) {\n        console.log(this.apiKey); \/\/ 'this' is now undefined or the global object\n    }\n}\n\nconst gateway = new PaymentGateway();\nsomeLibrary.on('success', gateway.handleResponse); \/\/ BOOM\n<\/code><\/pre>\n<p>In strict mode, <code>this<\/code> became <code>undefined<\/code>, and the process crashed. Because this happened inside a critical event listener, the error wasn&#8217;t caught by the global try-catch, and the entire payment service entered a crash-loop.<\/p>\n<p>The &#8220;best way&#8221; to distinguish an engineer from a pretender is their mastery of execution contexts. You must understand the Lexical Environment, the Variable Environment, and how the <code>this<\/code> value is determined at runtime based on the <em>call site<\/em>, not the <em>definition site<\/em> (unless using arrow functions, which capture the lexical <code>this<\/code>).<\/p>\n<h3><span class=\"ez-toc-section\" id=\"THE_EVOLUTION_OF_ASYNCHRONOUS_IO_THE_%E2%80%9CBEST_WAY%E2%80%9D\"><\/span>THE EVOLUTION OF ASYNCHRONOUS I\/O: THE &#8220;BEST WAY&#8221;<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>To fix the <code>fs.readFile<\/code> disaster, we had to move away from the &#8220;load everything into memory&#8221; mindset. We had to embrace Streams. This is the hallmark of a Senior Engineer: knowing when to stop treating data as a monolithic block and start treating it as a flow.<\/p>\n<p>Here is the final, robust implementation that saved the migration (too late, but it\u2019s there now):<\/p>\n<pre class=\"codehilite\"><code class=\"language-javascript\">\/\/ Version 3: The Professional Approach (Streams + Pipeline)\nconst fs = require('fs');\nconst { pipeline } = require('stream\/promises');\nconst JSONStream = require('JSONStream'); \/\/ For parsing large JSON without OOM\n\nasync function processConfig(path) {\n    try {\n        await pipeline(\n            fs.createReadStream(path, { encoding: 'utf8' }),\n            JSONStream.parse('*'),\n            async function* (source) {\n                for await (const chunk of source) {\n                    \/\/ Process each piece of the config individually\n                    \/\/ This keeps memory usage constant (O(1)) regardless of file size\n                    yield doSomethingWithChunk(chunk);\n                }\n            }\n        );\n    } catch (err) {\n        \/\/ Proper error handling that doesn't kill the process\n        process.stderr.write(`Critical I\/O Failure: ${err.message}\\n`);\n    }\n}\n<\/code><\/pre>\n<p>This implementation uses <code>fs.createReadStream<\/code> to read the file in 64KB chunks. It uses a transform stream to parse the JSON incrementally. The memory footprint stays at roughly 100MB, whether the file is 5MB or 5GB. This is how you build enterprise software. This is the <strong>best way<\/strong> to handle I\/O in Node.js.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"THE_EVENT_LOOP_MACROTASKS_VS_MICROTASKS\"><\/span>THE EVENT LOOP: MACROTASKS VS. MICROTASKS<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>If I ask a candidate to explain the event loop and they don&#8217;t mention the <code>libuv<\/code> thread pool or the difference between <code>setImmediate<\/code> and <code>process.nextTick<\/code>, the interview is over. <\/p>\n<p>During our migration, we had a service that was supposed to log analytics data in the background. The developer used <code>process.nextTick<\/code> for the logging calls, thinking it was &#8220;faster.&#8221; <\/p>\n<pre class=\"codehilite\"><code class=\"language-javascript\">function logAnalytics(data) {\n    process.nextTick(() =&gt; {\n        \/\/ Heavy synchronous logging logic\n        sendToAnalyticsServer(data);\n    });\n}\n<\/code><\/pre>\n<p>What they didn&#8217;t realize is that <code>process.nextTick<\/code> queues tasks in the &#8220;Next Tick Queue,&#8221; which is processed <em>immediately after<\/em> the current operation and <em>before<\/em> the event loop continues to the next phase. By flooding the Next Tick Queue, they effectively starved the I\/O poll phase. The server stopped accepting new TCP connections because it was too busy processing &#8220;background&#8221; analytics.<\/p>\n<p>The <strong>best way<\/strong> to handle this would have been <code>setImmediate<\/code>, which places the task in the &#8220;Check&#8221; phase of the event loop, allowing the &#8220;Poll&#8221; phase to handle incoming I\/O first. This is basic Node.js 101, yet it cost us millions.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"THE_ANATOMY_OF_A_STACK_OVERFLOW\"><\/span>THE ANATOMY OF A STACK OVERFLOW<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>We also encountered a recursive function used for traversing a deeply nested category tree. The developer didn&#8217;t account for the fact that V8 has a limited call stack size.<\/p>\n<pre class=\"codehilite\"><code class=\"language-javascript\">function findCategory(tree, id) {\n    if (tree.id === id) return tree;\n    for (const child of tree.children) {\n        const found = findCategory(child, id); \/\/ Recursive call\n        if (found) return found;\n    }\n    return null;\n}\n<\/code><\/pre>\n<p>When the category tree grew to 15,000 nodes deep (thanks to a bug in the admin tool), this function threw <code>RangeError: Maximum call stack size exceeded<\/code>. <\/p>\n<p>In Node.js v20, you can&#8217;t just increase the stack size and hope for the best. You have to write better code. The <strong>best way<\/strong> to handle deep recursion in JavaScript is to either use a trampoline function or, better yet, convert the recursive algorithm into an iterative one using an explicit stack array. This moves the data from the Call Stack (which is small) to the Heap (which is large).<\/p>\n<h3><span class=\"ez-toc-section\" id=\"THE_HIDDEN_COST_OF_NPM_INSTALL\"><\/span>THE HIDDEN COST OF NPM INSTALL<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>Our <code>node_modules<\/code> folder for the migration project was 2.4GB. Why? Because the juniors didn&#8217;t know how to use <code>npm explain<\/code> or <code>npm prune<\/code>. They were installing entire libraries like <code>lodash<\/code> just to use a single <code>cloneDeep<\/code> function.<\/p>\n<pre class=\"codehilite\"><code class=\"language-bash\">$ npm explain lodash\nlodash@4.17.21\nnode_modules\/lodash\n  lodash@&quot;^4.17.21&quot; from the-monolith@1.0.0\n  nested-dependency-a@1.2.3\n    lodash@&quot;^4.17.21&quot; from nested-dependency-a@1.2.3\n<\/code><\/pre>\n<p>They didn&#8217;t realize that <code>lodash<\/code> was being bundled multiple times in different versions, leading to massive memory overhead and slow startup times. They didn&#8217;t understand the difference between <code>dependencies<\/code> and <code>devDependencies<\/code>, resulting in test frameworks like Jest being deployed to production containers. This increased our cold-start time in AWS Lambda by 8 seconds, causing thousands of request timeouts.<\/p>\n<h3><span class=\"ez-toc-section\" id=\"THE_%E2%80%9CBEST_WAY%E2%80%9D_TO_MASTERY_A_MANDATORY_READING_LIST\"><\/span>THE &#8220;BEST WAY&#8221; TO MASTERY: A MANDATORY READING LIST<span class=\"ez-toc-section-end\"><\/span><\/h3>\n<p>If you want to call yourself a Senior Software Architect, stop reading &#8220;Top 10 React Hooks&#8221; articles. You are a professional; start acting like one. The <strong>best way<\/strong> to actually understand the language you get paid to write is to consume the source of truth.<\/p>\n<ol>\n<li><strong>The ECMAScript\u00ae 2023 Language Specification (ECMA-262):<\/strong> Read it. All of it. Understand the difference between a &#8220;Record&#8221; and an &#8220;Object.&#8221; Understand the &#8220;Abstract Operations&#8221; that the engine performs.<\/li>\n<li><strong>The V8 Blog (v8.dev):<\/strong> If you don&#8217;t know what &#8220;Pointer Compression&#8221; or &#8220;Concurrent Marking&#8221; is, you don&#8217;t know why your Node.js process is behaving the way it is.<\/li>\n<li><strong>Node.js Internal Documentation:<\/strong> Specifically, the <code>src<\/code> folder in the Node.js GitHub repository. Look at the C++ hooks for <code>async_hooks<\/code>. Understand how the <code>Environment<\/code> class manages the isolate.<\/li>\n<li><strong>&#8220;High Performance JavaScript&#8221; by Nicholas C. Zakas:<\/strong> It\u2019s old, but the principles of DOM interaction and loop optimization are still more relevant than 90% of what\u2019s on Medium today.<\/li>\n<li><strong>The &#8220;Don&#8217;t Block the Event Loop&#8221; Guide (nodejs.org):<\/strong> This should be tattooed on the inside of your eyelids.<\/li>\n<\/ol>\n<p>We are currently rebuilding the migration from scratch. This time, there are no frameworks allowed until the team can pass a 4-hour exam on V8 memory management and the libuv thread pool. It might seem harsh, but it\u2019s cheaper than a $50 million failure.<\/p>\n<p>If you think this is too much work, do us all a favor and go back to designing CSS buttons. Leave the architecture to the engineers.<\/p>\n<hr \/>\n<p><strong>Post-Mortem Status:<\/strong> CLOSED<br \/>\n<strong>Resolution:<\/strong> REWRITE IN PROGRESS<br \/>\n<strong>Architect Signature:<\/strong> <em>[REDACTED]<\/em><br \/>\n<strong>Date:<\/strong> 2024-05-15<br \/>\n<strong>Node Version:<\/strong> 20.10.0 (Strict Enforcement)<\/p>\n","protected":false},"excerpt":{"rendered":"<p>text FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed &#8211; JavaScript heap out of memory 1: 0x101304560 node::Abort() [\/usr\/local\/bin\/node] 2: 0x10130578c node::OnFatalError(char const, char const) [\/usr\/local\/bin\/node] 3: 0x1014a8340 v8::Utils::ReportOOMFailure(v8::internal::Isolate, char const, bool) [\/usr\/local\/bin\/node] 4: 0x1014a82d8 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate, char const, bool) [\/usr\/local\/bin\/node] 5: 0x101645e90 v8::internal::Heap::FatalProcessOutOfMemory(char const) [\/usr\/local\/bin\/node] 6: 0x101647464 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [\/usr\/local\/bin\/node] 7: 0x101643d1c v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [\/usr\/local\/bin\/node] &#8230; <a title=\"Best Way to Learn JavaScript: A Step-by-Step Guide\" class=\"read-more\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/\" aria-label=\"Read more  on Best Way to Learn JavaScript: A Step-by-Step Guide\">Read more<\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-4884","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.0 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Best Way to Learn JavaScript: A Step-by-Step Guide - ITSupportWale<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Best Way to Learn JavaScript: A Step-by-Step Guide - ITSupportWale\" \/>\n<meta property=\"og:description\" content=\"text FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed &#8211; JavaScript heap out of memory 1: 0x101304560 node::Abort() [\/usr\/local\/bin\/node] 2: 0x10130578c node::OnFatalError(char const, char const) [\/usr\/local\/bin\/node] 3: 0x1014a8340 v8::Utils::ReportOOMFailure(v8::internal::Isolate, char const, bool) [\/usr\/local\/bin\/node] 4: 0x1014a82d8 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate, char const, bool) [\/usr\/local\/bin\/node] 5: 0x101645e90 v8::internal::Heap::FatalProcessOutOfMemory(char const) [\/usr\/local\/bin\/node] 6: 0x101647464 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [\/usr\/local\/bin\/node] 7: 0x101643d1c v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [\/usr\/local\/bin\/node] ... Read more\" \/>\n<meta property=\"og:url\" content=\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/\" \/>\n<meta property=\"og:site_name\" content=\"ITSupportWale\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\" \/>\n<meta property=\"article:published_time\" content=\"2026-09-16T18:48:07+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png\" \/>\n\t<meta property=\"og:image:width\" content=\"512\" \/>\n\t<meta property=\"og:image:height\" content=\"512\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/png\" \/>\n<meta name=\"author\" content=\"Techie\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Techie\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"13 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/\"},\"author\":{\"name\":\"Techie\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\"},\"headline\":\"Best Way to Learn JavaScript: A Step-by-Step Guide\",\"datePublished\":\"2026-09-16T18:48:07+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/\"},\"wordCount\":1783,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/\",\"name\":\"Best Way to Learn JavaScript: A Step-by-Step Guide - ITSupportWale\",\"isPartOf\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\"},\"datePublished\":\"2026-09-16T18:48:07+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/itsupportwale.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Best Way to Learn JavaScript: A Step-by-Step Guide\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#website\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"name\":\"ITSupportWale\",\"description\":\"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides\",\"publisher\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#organization\",\"name\":\"itsupportwale\",\"url\":\"https:\/\/itsupportwale.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"contentUrl\":\"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png\",\"width\":1119,\"height\":144,\"caption\":\"itsupportwale\"},\"image\":{\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/\"},\"sameAs\":[\"https:\/\/www.facebook.com\/Itsupportwale-298547177495978\"]},{\"@type\":\"Person\",\"@id\":\"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d\",\"name\":\"Techie\",\"sameAs\":[\"https:\/\/itsupportwale.com\",\"iswblogadmin\"],\"url\":\"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Best Way to Learn JavaScript: A Step-by-Step Guide - ITSupportWale","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/","og_locale":"en_US","og_type":"article","og_title":"Best Way to Learn JavaScript: A Step-by-Step Guide - ITSupportWale","og_description":"text FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed &#8211; JavaScript heap out of memory 1: 0x101304560 node::Abort() [\/usr\/local\/bin\/node] 2: 0x10130578c node::OnFatalError(char const, char const) [\/usr\/local\/bin\/node] 3: 0x1014a8340 v8::Utils::ReportOOMFailure(v8::internal::Isolate, char const, bool) [\/usr\/local\/bin\/node] 4: 0x1014a82d8 v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate, char const, bool) [\/usr\/local\/bin\/node] 5: 0x101645e90 v8::internal::Heap::FatalProcessOutOfMemory(char const) [\/usr\/local\/bin\/node] 6: 0x101647464 v8::internal::Heap::RecomputeLimits(v8::internal::GarbageCollector) [\/usr\/local\/bin\/node] 7: 0x101643d1c v8::internal::Heap::PerformGarbageCollection(v8::internal::GarbageCollector, v8::GCCallbackFlags) [\/usr\/local\/bin\/node] ... Read more","og_url":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/","og_site_name":"ITSupportWale","article_publisher":"https:\/\/www.facebook.com\/Itsupportwale-298547177495978","article_published_time":"2026-09-16T18:48:07+00:00","og_image":[{"width":512,"height":512,"url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2021\/05\/android-chrome-512x512-1.png","type":"image\/png"}],"author":"Techie","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Techie","Est. reading time":"13 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#article","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/"},"author":{"name":"Techie","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d"},"headline":"Best Way to Learn JavaScript: A Step-by-Step Guide","datePublished":"2026-09-16T18:48:07+00:00","mainEntityOfPage":{"@id":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/"},"wordCount":1783,"commentCount":0,"publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/","url":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/","name":"Best Way to Learn JavaScript: A Step-by-Step Guide - ITSupportWale","isPartOf":{"@id":"https:\/\/itsupportwale.com\/blog\/#website"},"datePublished":"2026-09-16T18:48:07+00:00","breadcrumb":{"@id":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/itsupportwale.com\/blog\/best-way-to-learn-javascript-a-step-by-step-guide\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/itsupportwale.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Best Way to Learn JavaScript: A Step-by-Step Guide"}]},{"@type":"WebSite","@id":"https:\/\/itsupportwale.com\/blog\/#website","url":"https:\/\/itsupportwale.com\/blog\/","name":"ITSupportWale","description":"Tips, Tricks, Fixed-Errors, Tutorials &amp; Guides","publisher":{"@id":"https:\/\/itsupportwale.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/itsupportwale.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/itsupportwale.com\/blog\/#organization","name":"itsupportwale","url":"https:\/\/itsupportwale.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","contentUrl":"https:\/\/itsupportwale.com\/blog\/wp-content\/uploads\/2023\/09\/cropped-Logo-trans-without-slogan.png","width":1119,"height":144,"caption":"itsupportwale"},"image":{"@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/Itsupportwale-298547177495978"]},{"@type":"Person","@id":"https:\/\/itsupportwale.com\/blog\/#\/schema\/person\/8c5a2b3d36396e0a8fd91ec8242fd46d","name":"Techie","sameAs":["https:\/\/itsupportwale.com","iswblogadmin"],"url":"https:\/\/itsupportwale.com\/blog\/author\/iswblogadmin\/"}]}},"_links":{"self":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4884","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/comments?post=4884"}],"version-history":[{"count":0,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/posts\/4884\/revisions"}],"wp:attachment":[{"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/media?parent=4884"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/categories?post=4884"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/itsupportwale.com\/blog\/wp-json\/wp\/v2\/tags?post=4884"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}