<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sheikh Mubashir</title>
    <description>The latest articles on DEV Community by Sheikh Mubashir (@mubashir).</description>
    <link>https://dev.to/mubashir</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F674222%2F69618942-011b-4e59-a5d1-96fe048ec021.jpg</url>
      <title>DEV Community: Sheikh Mubashir</title>
      <link>https://dev.to/mubashir</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/mubashir"/>
    <language>en</language>
    <item>
      <title>Demystifying JavaScript: Understanding Execution Contexts, Hoisting, and Type Conversion</title>
      <dc:creator>Sheikh Mubashir</dc:creator>
      <pubDate>Fri, 11 Oct 2024 12:48:59 +0000</pubDate>
      <link>https://dev.to/mubashir/demystifying-javascript-understanding-execution-contexts-hoisting-and-type-conversion-11j9</link>
      <guid>https://dev.to/mubashir/demystifying-javascript-understanding-execution-contexts-hoisting-and-type-conversion-11j9</guid>
      <description>&lt;p&gt;JavaScript may seem simple on the surface, but under the hood, there’s a lot happening. Today, we’ll explore some essential concepts like execution contexts, hoisting, primitive vs. non-primitive data types, and type conversion. These are crucial to understand if you want to write better, bug-free code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqhl27yg9fjaa3oro6dh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqhl27yg9fjaa3oro6dh.png" alt="Image description" width="800" height="246"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Global Execution Context and Lexical Environment&lt;br&gt;
When you run a JavaScript file in the browser, the code gets executed line by line in the call stack. However, before any of your code runs, a global execution context is created. This context sets up the this and window objects. In Node.js, the equivalent of window is global, and if you compare the two, you'll find that window === global returns true.&lt;/p&gt;

&lt;p&gt;Whenever you call a function, a new lexical environment is created. The global execution context is the first to be created, and all functions defined inside it can access its variables. This is how JavaScript’s scope chain works — you can access variables in the outer (global) scope from inside a function.&lt;/p&gt;

&lt;p&gt;Hoisting: Variables and Functions&lt;br&gt;
JavaScript has a mechanism called hoisting, where variables and functions are “moved” to the top of their scope during compilation. Here’s how it works:&lt;/p&gt;

&lt;p&gt;Variables: Variables declared with var are partially hoisted, meaning you can reference them before they are initialized, but their value will be undefined until the line where they are initialized is reached.&lt;br&gt;
Functions: Functions declared with the function declaration syntax are fully hoisted, meaning you can call the function even before its declaration in the code.&lt;br&gt;
Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log(a); // undefined
var a = 5;

console.log(b); // Error: b is not defined
let b = 10;

hoistedFunction(); // Works!
function hoistedFunction() {
  console.log('This function is hoisted!');
}

notHoistedFunction(); // Error: notHoistedFunction is not a function
var notHoistedFunction = function() {
  console.log('This function is not hoisted!');
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, let and const are not hoisted like var, and function expressions (like notHoistedFunction) are only defined at runtime.&lt;/p&gt;

&lt;p&gt;Primitive vs. Non-Primitive Types&lt;br&gt;
JavaScript has two types of data: primitive and non-primitive.&lt;/p&gt;

&lt;p&gt;Primitive types include string, number, boolean, undefined, null, symbol, and bigint. These are immutable, meaning their values cannot be changed. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let x = 'hello';
x[0] = 'H'; // This won’t change the string, it stays 'hello'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Non-primitive types are objects, arrays, and functions. These are mutable, and their values can be changed because they are passed by reference. For instance:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;let obj1 = { name: 'John' };
let obj2 = obj1; // Both obj1 and obj2 now reference the same object
obj2.name = 'Doe';
console.log(obj1.name); // Outputs: Doe
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To avoid modifying the original object, you can create a shallow copy using Object.assign() or the spread operator (...). For deep copies, which copy nested objects, use JSON.parse() and JSON.stringify().&lt;/p&gt;

&lt;p&gt;Example Code Snippet: Shallow Copy vs Deep Copy&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Shallow copy example
let obj1 = { name: 'John', details: { age: 30 } };
let obj2 = { ...obj1 }; // Shallow copy
obj2.details.age = 40;
console.log(obj1.details.age); // Output: 40 (Shallow copy affects the original)

// Deep copy example
let obj3 = JSON.parse(JSON.stringify(obj1)); // Deep copy
obj3.details.age = 50;
console.log(obj1.details.age); // Output: 40 (Deep copy doesn’t affect the original)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Type Conversion and Comparison&lt;br&gt;
JavaScript is a dynamically typed language, meaning you don’t have to specify variable types explicitly. However, this can sometimes lead to unexpected behavior, especially when using comparison operators.&lt;/p&gt;

&lt;p&gt;Always prefer using triple equals (===) over double equals (==) to avoid type coercion. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log(0 == '0'); // true (type coercion happens)
console.log(0 === '0'); // false (no type coercion)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For special cases, like comparing NaN, use Object.is() because NaN === NaN returns false.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log(NaN === NaN); // false
console.log(Object.is(NaN, NaN)); // true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;JavaScript’s Runtime and Node.js&lt;br&gt;
JavaScript runs on a single-threaded, synchronous runtime, which means it can only execute one task at a time. This might seem limiting, but JavaScript handles asynchronous tasks efficiently by using the Web API and callback queue. Here’s how it works:&lt;/p&gt;

&lt;p&gt;When JavaScript encounters an async task (like setTimeout or an HTTP request), it sends the task to the Web API.&lt;br&gt;
The call stack continues to execute the remaining code.&lt;br&gt;
Once the async task is complete, it is added to the callback queue and will execute when the call stack is empty.&lt;br&gt;
Node.js extends this runtime to the server-side, using the V8 engine and a non-blocking I/O system powered by libuv. Node.js introduced the idea of a single-threaded event loop that can handle multiple requests without blocking other operations.&lt;/p&gt;

&lt;p&gt;By understanding how JavaScript handles execution contexts, hoisting, type conversion, and asynchronous tasks, you’ll be able to write cleaner and more efficient code. With JavaScript’s dynamic nature, tools like TypeScript can help you avoid common pitfalls by providing static type checks that make your code production-ready.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Mastering JavaScript: Avoiding Pitfalls with Memory Management and Asynchronous Execution</title>
      <dc:creator>Sheikh Mubashir</dc:creator>
      <pubDate>Wed, 09 Oct 2024 09:03:39 +0000</pubDate>
      <link>https://dev.to/mubashir/mastering-javascript-avoiding-pitfalls-with-memory-management-and-asynchronous-execution-23eg</link>
      <guid>https://dev.to/mubashir/mastering-javascript-avoiding-pitfalls-with-memory-management-and-asynchronous-execution-23eg</guid>
      <description>&lt;p&gt;As JavaScript developers, understanding how the language handles tasks like memory management and asynchronous code execution is crucial for writing efficient code. Today, we’ll dive into how JavaScript’s engine optimizes code and manages memory, while also exploring its single-threaded, asynchronous nature.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81xnag6cf02svrb6fk51.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F81xnag6cf02svrb6fk51.png" alt="Image description" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Inline Caching and Code Optimization&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When it comes to optimization, compilers use techniques like inline caching to make code faster. For this to work efficiently, your code needs to be predictable — not just for humans but also for the machine. To help the compiler optimize code, it’s best to avoid certain built-in keywords like eval(), arguments, for in, delete, and with. These keywords can introduce hidden classes, which slow down the compiler’s ability to optimize your code.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Call Stack and Memory Heap&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JavaScript runs code using two main components: the call stack and the memory heap.&lt;/p&gt;

&lt;p&gt;The memory heap is where all the values and objects are stored in random order.&lt;br&gt;
The call stack keeps track of the functions currently being executed, following a First In, Last Out (FILO) pattern.&lt;br&gt;
One common issue developers face is stack overflow, which happens when a function calls itself recursively or repeatedly without breaking the loop. The browser eventually runs out of memory and crashes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Code Snippet: Stack Overflow Example&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function recursiveFunction() {
  return recursiveFunction(); // This will cause a stack overflow
}

recursiveFunction();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the function keeps calling itself with no end, causing the call stack to fill up and resulting in a stack overflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Garbage Collection and Memory Leaks&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;JavaScript is a garbage-collected language, which means it automatically removes unused variables and objects from the memory heap. This process is handled by the mark-and-sweep algorithm, and unlike in languages like C, you can’t manually control memory management in JavaScript. While this automatic process makes things easier, there are common mistakes that can lead to memory leaks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common Causes of Memory Leaks:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Global variables: If you declare global variables that are never cleaned up, they stay in memory.&lt;br&gt;
Event listeners: Failing to remove event listeners after they’re no longer needed can cause memory to fill up.&lt;br&gt;
setTimeout functions: Similar to event listeners, if setTimeout is not cleared after use, it can lead to a memory leak.&lt;br&gt;
Single-Threaded and Asynchronous Execution&lt;br&gt;
JavaScript is a single-threaded and synchronous language, meaning it can handle one task at a time. This might seem limiting, but JavaScript is also powerful when it comes to handling asynchronous tasks.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s how it works:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When JavaScript encounters an async task, such as a network request, it sends it to the Web APIs (in the browser).&lt;br&gt;
While the async task is handled in the background, the synchronous code continues to execute.&lt;br&gt;
Once the async task is complete, the result is pushed into the callback queue.&lt;br&gt;
If the call stack is empty, JavaScript takes the result from the callback queue and pushes it onto the call stack to execute.&lt;br&gt;
This is how JavaScript can handle tasks like HTTP requests without freezing the page, even though it runs on a single thread.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example Code Snippet: Asynchronous Code Execution&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;console.log('Start');

setTimeout(() =&amp;gt; {
  console.log('Async Task Complete');
}, 3000); // This runs after 3 seconds, but JS doesn't block the next line

console.log('End');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, the message “Async Task Complete” appears after 3 seconds, but “End” prints immediately because the async task runs in the background.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Node.js and JavaScript Runtime&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before Node.js came along in 2009, JavaScript could only run inside browsers. Node.js, created by Ryan Dahl, allows JavaScript to run outside the browser. Node.js is built using C++ and uses the V8 engine (the same engine that runs JavaScript in Chrome) to handle tasks. It is known for its non-blocking I/O and single-threaded nature, meaning it handles multiple tasks simultaneously without using multiple threads.&lt;/p&gt;

&lt;p&gt;Node.js introduced the concept of single-threaded, non-blocking architecture, allowing it to handle I/O operations (like file reading) efficiently without blocking other operations.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>webdev</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
    <item>
      <title>Why JavaScript is Not Just an Interpreted Language: Understanding JIT Compilation</title>
      <dc:creator>Sheikh Mubashir</dc:creator>
      <pubDate>Tue, 01 Oct 2024 08:54:26 +0000</pubDate>
      <link>https://dev.to/mubashir/why-javascript-is-not-just-an-interpreted-language-understanding-jit-compilation-4ehd</link>
      <guid>https://dev.to/mubashir/why-javascript-is-not-just-an-interpreted-language-understanding-jit-compilation-4ehd</guid>
      <description>&lt;p&gt;When it comes to translating code into machine code, there are two main approaches: interpreters and compilers. JavaScript is often referred to as an interpreted language, but that’s not entirely accurate, and I’ll explain why.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Interpreters vs. Compilers&lt;/strong&gt;&lt;br&gt;
An interpreter translates code line by line, which makes it great for quickly running code. It’s a fast way to start execution, but there’s a downside — it doesn’t optimize repetitive tasks. For example, if your code has a loop that repeats the same result, the interpreter will process it each time without any optimization, slowing things down.&lt;/p&gt;

&lt;p&gt;On the other hand, a compiler takes the entire code in one go and translates it into machine code. This process takes longer at first, but after the initial compilation, it runs much faster. That’s because compilers can optimize repetitive tasks, like loops, making the code more efficient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enter JIT (Just-In-Time) Compiler&lt;/strong&gt;&lt;br&gt;
In the late 2000s, engineers saw the strengths of both interpreters and compilers and decided to create something better — a JIT (Just-In-Time) compiler. This hybrid approach combines the best of both worlds.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Here’s how it works:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When you give a JavaScript file to the browser, the code goes through a parser, which converts it into an Abstract Syntax Tree (AST).&lt;br&gt;
At this point, there’s a decision to make:&lt;br&gt;
If the code doesn’t need optimization, it goes directly to the interpreter, which translates the code to machine-readable instructions (binary).&lt;br&gt;
If the code has repetitive or complex tasks, a profiler detects the need for optimization and forwards it to the compiler, which optimizes the code and translates it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;here is the best diagram for a better understanding&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopg2jb7ewfsogzfn3qpn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopg2jb7ewfsogzfn3qpn.png" alt="Image description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, when someone asks, “Is JavaScript an interpreted language?” you can say “technically yes”, but it depends on the implementation. JavaScript uses both an interpreter and a compiler, thanks to JIT compilation.&lt;/p&gt;

&lt;p&gt;Here’s an example to demonstrate the efficiency difference between an interpreter and a compiler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function calculateSum() {
  let sum = 0;
  for (let i = 0; i &amp;lt; 1000000; i++) {
    sum += i;
  }
  return sum;
}

console.log(calculateSum());
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this example, an interpreter would go through each iteration of the loop one by one. A JIT compiler, on the other hand, would notice that the loop can be optimized, speeding up execution after the first run.&lt;/p&gt;

&lt;p&gt;Conclusion&lt;br&gt;
Understanding how JavaScript works under the hood helps you appreciate its flexibility and efficiency. The combination of interpreters and compilers (thanks to JIT) allows JavaScript to run quickly and efficiently in modern browsers.&lt;/p&gt;

&lt;p&gt;Next time someone calls JavaScript an interpreted language, you can explain that while it starts out that way, it can also behave like a compiled language when optimization is needed.&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>programming</category>
      <category>webdev</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
