Why Is This Undefined? JavaScript Traps for Python Programmers

Equality and Type Coercion

The Double Equals (==) vs Triple Equals (===)

<span>// == performs type coercion</span>
<span>0</span> <span>==</span> <span>'</span><span>0</span><span>'</span> <span>// true</span>
<span>0</span> <span>==</span> <span>''</span> <span>// true</span>
<span>false</span> <span>==</span> <span>'</span><span>0</span><span>'</span> <span>// true</span>
<span>false</span> <span>==</span> <span>[]</span> <span>// true</span>
<span>null</span> <span>==</span> <span>undefined</span> <span>// true</span>
<span>// === strict equality (no type coercion)</span>
<span>0</span> <span>===</span> <span>'</span><span>0</span><span>'</span> <span>// false</span>
<span>0</span> <span>===</span> <span>''</span> <span>// false</span>
<span>false</span> <span>===</span> <span>'</span><span>0</span><span>'</span> <span>// false</span>
<span>// == performs type coercion</span>
<span>0</span> <span>==</span> <span>'</span><span>0</span><span>'</span>           <span>// true</span>
<span>0</span> <span>==</span> <span>''</span>            <span>// true</span>
<span>false</span> <span>==</span> <span>'</span><span>0</span><span>'</span>       <span>// true</span>
<span>false</span> <span>==</span> <span>[]</span>        <span>// true</span>
<span>null</span> <span>==</span> <span>undefined</span>  <span>// true</span>

<span>// === strict equality (no type coercion)</span>
<span>0</span> <span>===</span> <span>'</span><span>0</span><span>'</span>          <span>// false</span>
<span>0</span> <span>===</span> <span>''</span>           <span>// false</span>
<span>false</span> <span>===</span> <span>'</span><span>0</span><span>'</span>      <span>// false</span>
// == performs type coercion 0 == '0' // true 0 == '' // true false == '0' // true false == [] // true null == undefined // true // === strict equality (no type coercion) 0 === '0' // false 0 === '' // false false === '0' // false

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python uses == for value equality and doesn’t do the same type of coercion.

Truthy and Falsy Values

<span>// Falsy values</span>
<span>Boolean</span><span>(</span><span>0</span><span>)</span> <span>// false</span>
<span>Boolean</span><span>(</span><span>''</span><span>)</span> <span>// false</span>
<span>Boolean</span><span>(</span><span>null</span><span>)</span> <span>// false</span>
<span>Boolean</span><span>(</span><span>undefined</span><span>)</span> <span>// false</span>
<span>Boolean</span><span>(</span><span>NaN</span><span>)</span> <span>// false</span>
<span>Boolean</span><span>(</span><span>false</span><span>)</span> <span>// false</span>
<span>// Everything else is truthy, including:</span>
<span>Boolean</span><span>([])</span> <span>// true (empty array is truthy!)</span>
<span>Boolean</span><span>({})</span> <span>// true (empty object is truthy!)</span>
<span>Boolean</span><span>(</span><span>'</span><span>0</span><span>'</span><span>)</span> <span>// true (string with zero is truthy!)</span>
<span>// Falsy values</span>
<span>Boolean</span><span>(</span><span>0</span><span>)</span>         <span>// false</span>
<span>Boolean</span><span>(</span><span>''</span><span>)</span>        <span>// false</span>
<span>Boolean</span><span>(</span><span>null</span><span>)</span>      <span>// false</span>
<span>Boolean</span><span>(</span><span>undefined</span><span>)</span> <span>// false</span>
<span>Boolean</span><span>(</span><span>NaN</span><span>)</span>       <span>// false</span>
<span>Boolean</span><span>(</span><span>false</span><span>)</span>     <span>// false</span>

<span>// Everything else is truthy, including:</span>
<span>Boolean</span><span>([])</span>        <span>// true (empty array is truthy!)</span>
<span>Boolean</span><span>({})</span>        <span>// true (empty object is truthy!)</span>
<span>Boolean</span><span>(</span><span>'</span><span>0</span><span>'</span><span>)</span>       <span>// true (string with zero is truthy!)</span>
// Falsy values Boolean(0) // false Boolean('') // false Boolean(null) // false Boolean(undefined) // false Boolean(NaN) // false Boolean(false) // false // Everything else is truthy, including: Boolean([]) // true (empty array is truthy!) Boolean({}) // true (empty object is truthy!) Boolean('0') // true (string with zero is truthy!)

Enter fullscreen mode Exit fullscreen mode

Python comparison: In Python, empty containers like [] and {} are falsy.

Variable Hoisting and Scoping

Hoisting

<span>// This works because of hoisting</span>
<span>x</span> <span>=</span> <span>5</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>);</span> <span>// 5</span>
<span>var</span> <span>x</span><span>;</span>
<span>// The above is interpreted as:</span>
<span>var</span> <span>x</span><span>;</span>
<span>x</span> <span>=</span> <span>5</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>);</span> <span>// 5</span>
<span>// But be careful with function-style declarations</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>y</span><span>);</span> <span>// undefined (not 5, only the declaration is hoisted)</span>
<span>var</span> <span>y</span> <span>=</span> <span>5</span><span>;</span>
<span>// let and const don't hoist the same way</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>z</span><span>);</span> <span>// ReferenceError</span>
<span>let</span> <span>z</span> <span>=</span> <span>5</span><span>;</span>
<span>// This works because of hoisting</span>
<span>x</span> <span>=</span> <span>5</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>);</span>  <span>// 5</span>
<span>var</span> <span>x</span><span>;</span>

<span>// The above is interpreted as:</span>
<span>var</span> <span>x</span><span>;</span>
<span>x</span> <span>=</span> <span>5</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>);</span>  <span>// 5</span>

<span>// But be careful with function-style declarations</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>y</span><span>);</span>  <span>// undefined (not 5, only the declaration is hoisted)</span>
<span>var</span> <span>y</span> <span>=</span> <span>5</span><span>;</span>

<span>// let and const don't hoist the same way</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>z</span><span>);</span>  <span>// ReferenceError</span>
<span>let</span> <span>z</span> <span>=</span> <span>5</span><span>;</span>
// This works because of hoisting x = 5; console.log(x); // 5 var x; // The above is interpreted as: var x; x = 5; console.log(x); // 5 // But be careful with function-style declarations console.log(y); // undefined (not 5, only the declaration is hoisted) var y = 5; // let and const don't hoist the same way console.log(z); // ReferenceError let z = 5;

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python doesn’t hoist variables or functions.

Variable Scoping

<span>// var is function-scoped</span>
<span>function</span> <span>varExample</span><span>()</span> <span>{</span>
<span>if </span><span>(</span><span>true</span><span>)</span> <span>{</span>
<span>var</span> <span>x</span> <span>=</span> <span>10</span><span>;</span>
<span>}</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>);</span> <span>// 10 (x is still accessible)</span>
<span>}</span>
<span>// let and const are block-scoped (more like Python)</span>
<span>function</span> <span>letExample</span><span>()</span> <span>{</span>
<span>if </span><span>(</span><span>true</span><span>)</span> <span>{</span>
<span>let</span> <span>y</span> <span>=</span> <span>10</span><span>;</span>
<span>}</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>y</span><span>);</span> <span>// ReferenceError: y is not defined</span>
<span>}</span>
<span>// var is function-scoped</span>
<span>function</span> <span>varExample</span><span>()</span> <span>{</span>
    <span>if </span><span>(</span><span>true</span><span>)</span> <span>{</span>
        <span>var</span> <span>x</span> <span>=</span> <span>10</span><span>;</span>
    <span>}</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>);</span>  <span>// 10 (x is still accessible)</span>
<span>}</span>

<span>// let and const are block-scoped (more like Python)</span>
<span>function</span> <span>letExample</span><span>()</span> <span>{</span>
    <span>if </span><span>(</span><span>true</span><span>)</span> <span>{</span>
        <span>let</span> <span>y</span> <span>=</span> <span>10</span><span>;</span>
    <span>}</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>y</span><span>);</span>  <span>// ReferenceError: y is not defined</span>
<span>}</span>
// var is function-scoped function varExample() { if (true) { var x = 10; } console.log(x); // 10 (x is still accessible) } // let and const are block-scoped (more like Python) function letExample() { if (true) { let y = 10; } console.log(y); // ReferenceError: y is not defined }

Enter fullscreen mode Exit fullscreen mode

Python comparison: All variables in Python are block-scoped.

Functions and this Context

this Binding

<span>const</span> <span>obj</span> <span>=</span> <span>{</span>
<span>name</span><span>:</span> <span>"</span><span>Object</span><span>"</span><span>,</span>
<span>sayHello</span><span>:</span> <span>function</span><span>()</span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>`Hello from </span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span>
<span>}</span>
<span>};</span>
<span>obj</span><span>.</span><span>sayHello</span><span>();</span> <span>// "Hello from Object"</span>
<span>const</span> <span>func</span> <span>=</span> <span>obj</span><span>.</span><span>sayHello</span><span>;</span>
<span>func</span><span>();</span> <span>// "Hello from undefined" (this is now the global context)</span>
<span>// Arrow functions don't have their own 'this'</span>
<span>const</span> <span>obj2</span> <span>=</span> <span>{</span>
<span>name</span><span>:</span> <span>"</span><span>Object2</span><span>"</span><span>,</span>
<span>sayHello</span><span>:</span> <span>()</span> <span>=></span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>`Hello from </span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span>
<span>}</span>
<span>};</span>
<span>obj2</span><span>.</span><span>sayHello</span><span>();</span> <span>// "Hello from undefined" (this refers to parent scope)</span>
<span>const</span> <span>obj</span> <span>=</span> <span>{</span>
    <span>name</span><span>:</span> <span>"</span><span>Object</span><span>"</span><span>,</span>
    <span>sayHello</span><span>:</span> <span>function</span><span>()</span> <span>{</span>
        <span>console</span><span>.</span><span>log</span><span>(</span><span>`Hello from </span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span>
    <span>}</span>
<span>};</span>

<span>obj</span><span>.</span><span>sayHello</span><span>();</span>  <span>// "Hello from Object"</span>

<span>const</span> <span>func</span> <span>=</span> <span>obj</span><span>.</span><span>sayHello</span><span>;</span>
<span>func</span><span>();</span>  <span>// "Hello from undefined" (this is now the global context)</span>

<span>// Arrow functions don't have their own 'this'</span>
<span>const</span> <span>obj2</span> <span>=</span> <span>{</span>
    <span>name</span><span>:</span> <span>"</span><span>Object2</span><span>"</span><span>,</span>
    <span>sayHello</span><span>:</span> <span>()</span> <span>=></span> <span>{</span>
        <span>console</span><span>.</span><span>log</span><span>(</span><span>`Hello from </span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span>`</span><span>);</span>
    <span>}</span>
<span>};</span>

<span>obj2</span><span>.</span><span>sayHello</span><span>();</span>  <span>// "Hello from undefined" (this refers to parent scope)</span>
const obj = { name: "Object", sayHello: function() { console.log(`Hello from ${this.name}`); } }; obj.sayHello(); // "Hello from Object" const func = obj.sayHello; func(); // "Hello from undefined" (this is now the global context) // Arrow functions don't have their own 'this' const obj2 = { name: "Object2", sayHello: () => { console.log(`Hello from ${this.name}`); } }; obj2.sayHello(); // "Hello from undefined" (this refers to parent scope)

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python uses explicit self parameter and doesn’t have the concept of this binding changing based on how the function is called.

Default Parameters

<span>// Default params</span>
<span>function</span> <span>greet</span><span>(</span><span>name</span> <span>=</span> <span>'</span><span>Guest</span><span>'</span><span>)</span> <span>{</span>
<span>return</span> <span>`Hello, </span><span>${</span><span>name</span><span>}</span><span>!`</span><span>;</span>
<span>}</span>
<span>// But watch out for falsy values</span>
<span>function</span> <span>badDefault</span><span>(</span><span>value</span> <span>=</span> <span>10</span><span>)</span> <span>{</span>
<span>return</span> <span>value</span><span>;</span>
<span>}</span>
<span>badDefault</span><span>(</span><span>0</span><span>);</span> <span>// Returns 0, not 10</span>
<span>badDefault</span><span>(</span><span>''</span><span>);</span> <span>// Returns '', not 10</span>
<span>badDefault</span><span>(</span><span>null</span><span>);</span> <span>// Returns null, not 10</span>
<span>badDefault</span><span>(</span><span>undefined</span><span>);</span> <span>// Returns 10</span>
<span>// Default params</span>
<span>function</span> <span>greet</span><span>(</span><span>name</span> <span>=</span> <span>'</span><span>Guest</span><span>'</span><span>)</span> <span>{</span>
    <span>return</span> <span>`Hello, </span><span>${</span><span>name</span><span>}</span><span>!`</span><span>;</span>
<span>}</span>

<span>// But watch out for falsy values</span>
<span>function</span> <span>badDefault</span><span>(</span><span>value</span> <span>=</span> <span>10</span><span>)</span> <span>{</span>
    <span>return</span> <span>value</span><span>;</span>
<span>}</span>

<span>badDefault</span><span>(</span><span>0</span><span>);</span>  <span>// Returns 0, not 10</span>
<span>badDefault</span><span>(</span><span>''</span><span>);</span>  <span>// Returns '', not 10</span>
<span>badDefault</span><span>(</span><span>null</span><span>);</span>  <span>// Returns null, not 10</span>
<span>badDefault</span><span>(</span><span>undefined</span><span>);</span>  <span>// Returns 10</span>
// Default params function greet(name = 'Guest') { return `Hello, ${name}!`; } // But watch out for falsy values function badDefault(value = 10) { return value; } badDefault(0); // Returns 0, not 10 badDefault(''); // Returns '', not 10 badDefault(null); // Returns null, not 10 badDefault(undefined); // Returns 10

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python’s default parameters are similar but don’t have issues with falsy values.

Function Arguments

<span>function</span> <span>sum</span><span>(</span><span>a</span><span>,</span> <span>b</span><span>)</span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>arguments</span><span>);</span> <span>// Arguments object contains all passed arguments</span>
<span>return</span> <span>a</span> <span>+</span> <span>b</span><span>;</span>
<span>}</span>
<span>sum</span><span>(</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>,</span> <span>4</span><span>);</span> <span>// Extra arguments are ignored but accessible via arguments</span>
<span>// Rest parameters (similar to Python's *args)</span>
<span>function</span> <span>betterSum</span><span>(...</span><span>numbers</span><span>)</span> <span>{</span>
<span>return</span> <span>numbers</span><span>.</span><span>reduce</span><span>((</span><span>total</span><span>,</span> <span>num</span><span>)</span> <span>=></span> <span>total</span> <span>+</span> <span>num</span><span>,</span> <span>0</span><span>);</span>
<span>}</span>
<span>betterSum</span><span>(</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>,</span> <span>4</span><span>);</span> <span>// 10</span>
<span>function</span> <span>sum</span><span>(</span><span>a</span><span>,</span> <span>b</span><span>)</span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>arguments</span><span>);</span>  <span>// Arguments object contains all passed arguments</span>
    <span>return</span> <span>a</span> <span>+</span> <span>b</span><span>;</span>
<span>}</span>

<span>sum</span><span>(</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>,</span> <span>4</span><span>);</span>  <span>// Extra arguments are ignored but accessible via arguments</span>

<span>// Rest parameters (similar to Python's *args)</span>
<span>function</span> <span>betterSum</span><span>(...</span><span>numbers</span><span>)</span> <span>{</span>
    <span>return</span> <span>numbers</span><span>.</span><span>reduce</span><span>((</span><span>total</span><span>,</span> <span>num</span><span>)</span> <span>=></span> <span>total</span> <span>+</span> <span>num</span><span>,</span> <span>0</span><span>);</span>
<span>}</span>

<span>betterSum</span><span>(</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>,</span> <span>4</span><span>);</span>  <span>// 10</span>
function sum(a, b) { console.log(arguments); // Arguments object contains all passed arguments return a + b; } sum(1, 2, 3, 4); // Extra arguments are ignored but accessible via arguments // Rest parameters (similar to Python's *args) function betterSum(...numbers) { return numbers.reduce((total, num) => total + num, 0); } betterSum(1, 2, 3, 4); // 10

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python uses *args and **kwargs for flexible argument handling.

Arrays and Objects

Array Behavior

<span>const</span> <span>arr</span> <span>=</span> <span>[</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>];</span>
<span>// Length can be modified directly</span>
<span>arr</span><span>.</span><span>length</span> <span>=</span> <span>1</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>arr</span><span>);</span> <span>// [1]</span>
<span>arr</span><span>.</span><span>length</span> <span>=</span> <span>5</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>arr</span><span>);</span> <span>// [1, empty × 4]</span>
<span>// Sparse arrays</span>
<span>const</span> <span>sparse</span> <span>=</span> <span>[];</span>
<span>sparse</span><span>[</span><span>0</span><span>]</span> <span>=</span> <span>1</span><span>;</span>
<span>sparse</span><span>[</span><span>2</span><span>]</span> <span>=</span> <span>3</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>sparse</span><span>);</span> <span>// [1, empty, 3]</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>sparse</span><span>.</span><span>length</span><span>);</span> <span>// 3</span>
<span>// forEach skips empty slots</span>
<span>sparse</span><span>.</span><span>forEach</span><span>(</span><span>x</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>));</span> <span>// Logs only 1 and 3</span>
<span>const</span> <span>arr</span> <span>=</span> <span>[</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>];</span>

<span>// Length can be modified directly</span>
<span>arr</span><span>.</span><span>length</span> <span>=</span> <span>1</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>arr</span><span>);</span>  <span>// [1]</span>

<span>arr</span><span>.</span><span>length</span> <span>=</span> <span>5</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>arr</span><span>);</span>  <span>// [1, empty × 4]</span>

<span>// Sparse arrays</span>
<span>const</span> <span>sparse</span> <span>=</span> <span>[];</span>
<span>sparse</span><span>[</span><span>0</span><span>]</span> <span>=</span> <span>1</span><span>;</span>
<span>sparse</span><span>[</span><span>2</span><span>]</span> <span>=</span> <span>3</span><span>;</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>sparse</span><span>);</span>  <span>// [1, empty, 3]</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>sparse</span><span>.</span><span>length</span><span>);</span>  <span>// 3</span>

<span>// forEach skips empty slots</span>
<span>sparse</span><span>.</span><span>forEach</span><span>(</span><span>x</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>));</span>  <span>// Logs only 1 and 3</span>
const arr = [1, 2, 3]; // Length can be modified directly arr.length = 1; console.log(arr); // [1] arr.length = 5; console.log(arr); // [1, empty × 4] // Sparse arrays const sparse = []; sparse[0] = 1; sparse[2] = 3; console.log(sparse); // [1, empty, 3] console.log(sparse.length); // 3 // forEach skips empty slots sparse.forEach(x => console.log(x)); // Logs only 1 and 3

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python lists don’t have sparse behavior and can’t have their length directly modified.

Array Methods That Modify In-Place

<span>const</span> <span>arr</span> <span>=</span> <span>[</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>];</span>
<span>// These modify the original array</span>
<span>arr</span><span>.</span><span>push</span><span>(</span><span>4</span><span>);</span> <span>// [1, 2, 3, 4]</span>
<span>arr</span><span>.</span><span>pop</span><span>();</span> <span>// [1, 2, 3], returns 4</span>
<span>arr</span><span>.</span><span>unshift</span><span>(</span><span>0</span><span>);</span> <span>// [0, 1, 2, 3]</span>
<span>arr</span><span>.</span><span>shift</span><span>();</span> <span>// [1, 2, 3], returns 0</span>
<span>arr</span><span>.</span><span>splice</span><span>(</span><span>1</span><span>,</span> <span>1</span><span>,</span> <span>5</span><span>);</span> <span>// [1, 5, 3], returns [2]</span>
<span>arr</span><span>.</span><span>sort</span><span>();</span> <span>// Sorts in-place</span>
<span>arr</span><span>.</span><span>reverse</span><span>();</span> <span>// Reverses in-place</span>
<span>// These create new arrays</span>
<span>const</span> <span>newArr</span> <span>=</span> <span>arr</span><span>.</span><span>map</span><span>(</span><span>x</span> <span>=></span> <span>x</span> <span>*</span> <span>2</span><span>);</span>
<span>const</span> <span>filtered</span> <span>=</span> <span>arr</span><span>.</span><span>filter</span><span>(</span><span>x</span> <span>=></span> <span>x</span> <span>></span> <span>1</span><span>);</span>
<span>const</span> <span>sliced</span> <span>=</span> <span>arr</span><span>.</span><span>slice</span><span>(</span><span>1</span><span>,</span> <span>2</span><span>);</span>
<span>const</span> <span>arr</span> <span>=</span> <span>[</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>];</span>

<span>// These modify the original array</span>
<span>arr</span><span>.</span><span>push</span><span>(</span><span>4</span><span>);</span>          <span>// [1, 2, 3, 4]</span>
<span>arr</span><span>.</span><span>pop</span><span>();</span>            <span>// [1, 2, 3], returns 4</span>
<span>arr</span><span>.</span><span>unshift</span><span>(</span><span>0</span><span>);</span>       <span>// [0, 1, 2, 3]</span>
<span>arr</span><span>.</span><span>shift</span><span>();</span>          <span>// [1, 2, 3], returns 0</span>
<span>arr</span><span>.</span><span>splice</span><span>(</span><span>1</span><span>,</span> <span>1</span><span>,</span> <span>5</span><span>);</span>  <span>// [1, 5, 3], returns [2]</span>
<span>arr</span><span>.</span><span>sort</span><span>();</span>           <span>// Sorts in-place</span>
<span>arr</span><span>.</span><span>reverse</span><span>();</span>        <span>// Reverses in-place</span>

<span>// These create new arrays</span>
<span>const</span> <span>newArr</span> <span>=</span> <span>arr</span><span>.</span><span>map</span><span>(</span><span>x</span> <span>=></span> <span>x</span> <span>*</span> <span>2</span><span>);</span>
<span>const</span> <span>filtered</span> <span>=</span> <span>arr</span><span>.</span><span>filter</span><span>(</span><span>x</span> <span>=></span> <span>x</span> <span>></span> <span>1</span><span>);</span>
<span>const</span> <span>sliced</span> <span>=</span> <span>arr</span><span>.</span><span>slice</span><span>(</span><span>1</span><span>,</span> <span>2</span><span>);</span>
const arr = [1, 2, 3]; // These modify the original array arr.push(4); // [1, 2, 3, 4] arr.pop(); // [1, 2, 3], returns 4 arr.unshift(0); // [0, 1, 2, 3] arr.shift(); // [1, 2, 3], returns 0 arr.splice(1, 1, 5); // [1, 5, 3], returns [2] arr.sort(); // Sorts in-place arr.reverse(); // Reverses in-place // These create new arrays const newArr = arr.map(x => x * 2); const filtered = arr.filter(x => x > 1); const sliced = arr.slice(1, 2);

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python differentiates between methods that modify in-place (like list.sort()) and functions that return new objects (like sorted(list)).

Object Quirks

<span>// Object keys are always strings or Symbols</span>
<span>const</span> <span>obj</span> <span>=</span> <span>{</span>
<span>1</span><span>:</span> <span>'</span><span>one</span><span>'</span><span>,</span>
<span>true</span><span>:</span> <span>'</span><span>yes</span><span>'</span>
<span>};</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>obj</span><span>[</span><span>1</span><span>]);</span> <span>// 'one'</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>obj</span><span>[</span><span>'</span><span>1</span><span>'</span><span>]);</span> <span>// 'one' (same property)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>obj</span><span>[</span><span>true</span><span>]);</span> <span>// 'yes'</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>obj</span><span>[</span><span>'</span><span>true</span><span>'</span><span>]);</span> <span>// 'yes' (same property)</span>
<span>// Object property access</span>
<span>const</span> <span>key</span> <span>=</span> <span>'</span><span>name</span><span>'</span><span>;</span>
<span>const</span> <span>person</span> <span>=</span> <span>{</span>
<span>name</span><span>:</span> <span>'</span><span>John</span><span>'</span>
<span>};</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>person</span><span>.</span><span>name</span><span>);</span> <span>// 'John'</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>person</span><span>[</span><span>'</span><span>name</span><span>'</span><span>]);</span> <span>// 'John'</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>person</span><span>[</span><span>key</span><span>]);</span> <span>// 'John'</span>
<span>// Object keys are always strings or Symbols</span>
<span>const</span> <span>obj</span> <span>=</span> <span>{</span>
    <span>1</span><span>:</span> <span>'</span><span>one</span><span>'</span><span>,</span>
    <span>true</span><span>:</span> <span>'</span><span>yes</span><span>'</span>
<span>};</span>

<span>console</span><span>.</span><span>log</span><span>(</span><span>obj</span><span>[</span><span>1</span><span>]);</span>      <span>// 'one'</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>obj</span><span>[</span><span>'</span><span>1</span><span>'</span><span>]);</span>    <span>// 'one' (same property)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>obj</span><span>[</span><span>true</span><span>]);</span>   <span>// 'yes'</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>obj</span><span>[</span><span>'</span><span>true</span><span>'</span><span>]);</span> <span>// 'yes' (same property)</span>

<span>// Object property access</span>
<span>const</span> <span>key</span> <span>=</span> <span>'</span><span>name</span><span>'</span><span>;</span>
<span>const</span> <span>person</span> <span>=</span> <span>{</span>
    <span>name</span><span>:</span> <span>'</span><span>John</span><span>'</span>
<span>};</span>

<span>console</span><span>.</span><span>log</span><span>(</span><span>person</span><span>.</span><span>name</span><span>);</span>    <span>// 'John'</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>person</span><span>[</span><span>'</span><span>name</span><span>'</span><span>]);</span> <span>// 'John'</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>person</span><span>[</span><span>key</span><span>]);</span>    <span>// 'John'</span>
// Object keys are always strings or Symbols const obj = { 1: 'one', true: 'yes' }; console.log(obj[1]); // 'one' console.log(obj['1']); // 'one' (same property) console.log(obj[true]); // 'yes' console.log(obj['true']); // 'yes' (same property) // Object property access const key = 'name'; const person = { name: 'John' }; console.log(person.name); // 'John' console.log(person['name']); // 'John' console.log(person[key]); // 'John'

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python dictionaries can have any hashable object as keys, not just strings.

Asynchronous JavaScript

Callbacks vs. Python’s Sequential Execution

<span>// Traditional callbacks</span>
<span>function</span> <span>fetchData</span><span>(</span><span>callback</span><span>)</span> <span>{</span>
<span>setTimeout</span><span>(()</span> <span>=></span> <span>{</span>
<span>callback</span><span>(</span><span>'</span><span>Data received</span><span>'</span><span>);</span>
<span>},</span> <span>1000</span><span>);</span>
<span>}</span>
<span>fetchData</span><span>(</span><span>data</span> <span>=></span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>data</span><span>);</span> <span>// Runs after 1 second</span>
<span>});</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Continuing execution</span><span>'</span><span>);</span> <span>// Runs immediately</span>
<span>// Traditional callbacks</span>
<span>function</span> <span>fetchData</span><span>(</span><span>callback</span><span>)</span> <span>{</span>
    <span>setTimeout</span><span>(()</span> <span>=></span> <span>{</span>
        <span>callback</span><span>(</span><span>'</span><span>Data received</span><span>'</span><span>);</span>
    <span>},</span> <span>1000</span><span>);</span>
<span>}</span>

<span>fetchData</span><span>(</span><span>data</span> <span>=></span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>data</span><span>);</span>  <span>// Runs after 1 second</span>
<span>});</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Continuing execution</span><span>'</span><span>);</span>  <span>// Runs immediately</span>
// Traditional callbacks function fetchData(callback) { setTimeout(() => { callback('Data received'); }, 1000); } fetchData(data => { console.log(data); // Runs after 1 second }); console.log('Continuing execution'); // Runs immediately

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python’s synchronous code executes sequentially unless you use async/await or threading.

Promises

<span>// Modern promise-based code</span>
<span>function</span> <span>fetchData</span><span>()</span> <span>{</span>
<span>return</span> <span>new</span> <span>Promise</span><span>((</span><span>resolve</span><span>,</span> <span>reject</span><span>)</span> <span>=></span> <span>{</span>
<span>setTimeout</span><span>(()</span> <span>=></span> <span>{</span>
<span>resolve</span><span>(</span><span>'</span><span>Data received</span><span>'</span><span>);</span>
<span>// or reject(new Error('Failed to fetch data'))</span>
<span>},</span> <span>1000</span><span>);</span>
<span>});</span>
<span>}</span>
<span>fetchData</span><span>()</span>
<span>.</span><span>then</span><span>(</span><span>data</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>data</span><span>))</span>
<span>.</span><span>catch</span><span>(</span><span>error</span> <span>=></span> <span>console</span><span>.</span><span>error</span><span>(</span><span>error</span><span>));</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Continuing execution</span><span>'</span><span>);</span> <span>// Runs before the promise resolves</span>
<span>// Modern promise-based code</span>
<span>function</span> <span>fetchData</span><span>()</span> <span>{</span>
    <span>return</span> <span>new</span> <span>Promise</span><span>((</span><span>resolve</span><span>,</span> <span>reject</span><span>)</span> <span>=></span> <span>{</span>
        <span>setTimeout</span><span>(()</span> <span>=></span> <span>{</span>
            <span>resolve</span><span>(</span><span>'</span><span>Data received</span><span>'</span><span>);</span>
            <span>// or reject(new Error('Failed to fetch data'))</span>
        <span>},</span> <span>1000</span><span>);</span>
    <span>});</span>
<span>}</span>

<span>fetchData</span><span>()</span>
    <span>.</span><span>then</span><span>(</span><span>data</span> <span>=></span> <span>console</span><span>.</span><span>log</span><span>(</span><span>data</span><span>))</span>
    <span>.</span><span>catch</span><span>(</span><span>error</span> <span>=></span> <span>console</span><span>.</span><span>error</span><span>(</span><span>error</span><span>));</span>

<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Continuing execution</span><span>'</span><span>);</span>  <span>// Runs before the promise resolves</span>
// Modern promise-based code function fetchData() { return new Promise((resolve, reject) => { setTimeout(() => { resolve('Data received'); // or reject(new Error('Failed to fetch data')) }, 1000); }); } fetchData() .then(data => console.log(data)) .catch(error => console.error(error)); console.log('Continuing execution'); // Runs before the promise resolves

Enter fullscreen mode Exit fullscreen mode

Python comparison: Similar to Python’s asyncio with async/await, but JavaScript has this pattern much more deeply embedded.

Async/Await

<span>// Even more modern async/await</span>
<span>async</span> <span>function</span> <span>getData</span><span>()</span> <span>{</span>
<span>try</span> <span>{</span>
<span>const</span> <span>data</span> <span>=</span> <span>await</span> <span>fetchData</span><span>();</span> <span>// fetchData returns a Promise</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>data</span><span>);</span>
<span>}</span> <span>catch </span><span>(</span><span>error</span><span>)</span> <span>{</span>
<span>console</span><span>.</span><span>error</span><span>(</span><span>error</span><span>);</span>
<span>}</span>
<span>}</span>
<span>getData</span><span>();</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Continuing execution</span><span>'</span><span>);</span> <span>// Still runs before async function completes</span>
<span>// Even more modern async/await</span>
<span>async</span> <span>function</span> <span>getData</span><span>()</span> <span>{</span>
    <span>try</span> <span>{</span>
        <span>const</span> <span>data</span> <span>=</span> <span>await</span> <span>fetchData</span><span>();</span>  <span>// fetchData returns a Promise</span>
        <span>console</span><span>.</span><span>log</span><span>(</span><span>data</span><span>);</span>
    <span>}</span> <span>catch </span><span>(</span><span>error</span><span>)</span> <span>{</span>
        <span>console</span><span>.</span><span>error</span><span>(</span><span>error</span><span>);</span>
    <span>}</span>
<span>}</span>

<span>getData</span><span>();</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Continuing execution</span><span>'</span><span>);</span>  <span>// Still runs before async function completes</span>
// Even more modern async/await async function getData() { try { const data = await fetchData(); // fetchData returns a Promise console.log(data); } catch (error) { console.error(error); } } getData(); console.log('Continuing execution'); // Still runs before async function completes

Enter fullscreen mode Exit fullscreen mode

Python comparison: The syntax is very similar to Python’s async/await.

Numeric Oddities

All Numbers are Floating Point

<span>console</span><span>.</span><span>log</span><span>(</span><span>0.1</span> <span>+</span> <span>0.2</span><span>);</span> <span>// 0.30000000000000004</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>0.1</span> <span>+</span> <span>0.2</span> <span>===</span> <span>0.3</span><span>);</span> <span>// false</span>
<span>// Integer arithmetic can be imprecise for large numbers</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>9007199254740992</span> <span>+</span> <span>1</span><span>);</span> <span>// 9007199254740992 (no change!)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>0.1</span> <span>+</span> <span>0.2</span><span>);</span>          <span>// 0.30000000000000004</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>0.1</span> <span>+</span> <span>0.2</span> <span>===</span> <span>0.3</span><span>);</span>  <span>// false</span>

<span>// Integer arithmetic can be imprecise for large numbers</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>9007199254740992</span> <span>+</span> <span>1</span><span>);</span> <span>// 9007199254740992 (no change!)</span>
console.log(0.1 + 0.2); // 0.30000000000000004 console.log(0.1 + 0.2 === 0.3); // false // Integer arithmetic can be imprecise for large numbers console.log(9007199254740992 + 1); // 9007199254740992 (no change!)

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python handles this better with arbitrary precision integers and the Decimal module.

Special Number Values

<span>console</span><span>.</span><span>log</span><span>(</span><span>1</span> <span>/</span> <span>0</span><span>);</span> <span>// Infinity</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>-</span><span>1</span> <span>/</span> <span>0</span><span>);</span> <span>// -Infinity</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>0</span> <span>/</span> <span>0</span><span>);</span> <span>// NaN</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>NaN</span> <span>===</span> <span>NaN</span><span>);</span> <span>// false (NaN is never equal to anything)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>Number</span><span>.</span><span>isNaN</span><span>(</span><span>NaN</span><span>));</span> <span>// true (proper way to check for NaN)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>1</span> <span>/</span> <span>0</span><span>);</span>               <span>// Infinity</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>-</span><span>1</span> <span>/</span> <span>0</span><span>);</span>              <span>// -Infinity</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>0</span> <span>/</span> <span>0</span><span>);</span>               <span>// NaN</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>NaN</span> <span>===</span> <span>NaN</span><span>);</span>         <span>// false (NaN is never equal to anything)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>Number</span><span>.</span><span>isNaN</span><span>(</span><span>NaN</span><span>));</span>   <span>// true (proper way to check for NaN)</span>
console.log(1 / 0); // Infinity console.log(-1 / 0); // -Infinity console.log(0 / 0); // NaN console.log(NaN === NaN); // false (NaN is never equal to anything) console.log(Number.isNaN(NaN)); // true (proper way to check for NaN)

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python raises exceptions for divide by zero instead of returning Infinity.

Type Conversion Surprises

<span>console</span><span>.</span><span>log</span><span>(</span><span>+</span><span>'</span><span>42</span><span>'</span><span>);</span> <span>// 42 (string to number)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>+</span><span>true</span><span>);</span> <span>// 1</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>+</span><span>'</span><span>abc</span><span>'</span><span>);</span> <span>// NaN</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>42</span> <span>+</span> <span>''</span><span>);</span> <span>// '42' (number to string)</span>
<span>console</span><span>.</span><span>log</span><span>({}</span> <span>+</span> <span>[]);</span> <span>// '[object Object]' (both convert to strings)</span>
<span>// The + operator</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>1</span> <span>+</span> <span>2</span><span>);</span> <span>// 3 (addition)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>1</span><span>'</span> <span>+</span> <span>'</span><span>2</span><span>'</span><span>);</span> <span>// '12' (string concatenation)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>1</span><span>'</span> <span>+</span> <span>2</span><span>);</span> <span>// '12' (number converts to string)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>1</span> <span>+</span> <span>'</span><span>2</span><span>'</span><span>);</span> <span>// '12' (number converts to string)</span>
<span>// But other operators convert strings to numbers</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>5</span><span>'</span> <span>-</span> <span>2</span><span>);</span> <span>// 3</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>5</span><span>'</span> <span>*</span> <span>2</span><span>);</span> <span>// 10</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>5</span><span>'</span> <span>/</span> <span>2</span><span>);</span> <span>// 2.5</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>+</span><span>'</span><span>42</span><span>'</span><span>);</span>     <span>// 42 (string to number)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>+</span><span>true</span><span>);</span>     <span>// 1</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>+</span><span>'</span><span>abc</span><span>'</span><span>);</span>    <span>// NaN</span>

<span>console</span><span>.</span><span>log</span><span>(</span><span>42</span> <span>+</span> <span>''</span><span>);</span>   <span>// '42' (number to string)</span>
<span>console</span><span>.</span><span>log</span><span>({}</span> <span>+</span> <span>[]);</span>   <span>// '[object Object]' (both convert to strings)</span>

<span>// The + operator</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>1</span> <span>+</span> <span>2</span><span>);</span>     <span>// 3 (addition)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>1</span><span>'</span> <span>+</span> <span>'</span><span>2</span><span>'</span><span>);</span> <span>// '12' (string concatenation)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>1</span><span>'</span> <span>+</span> <span>2</span><span>);</span>   <span>// '12' (number converts to string)</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>1</span> <span>+</span> <span>'</span><span>2</span><span>'</span><span>);</span>   <span>// '12' (number converts to string)</span>

<span>// But other operators convert strings to numbers</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>5</span><span>'</span> <span>-</span> <span>2</span><span>);</span>   <span>// 3</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>5</span><span>'</span> <span>*</span> <span>2</span><span>);</span>   <span>// 10</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>5</span><span>'</span> <span>/</span> <span>2</span><span>);</span>   <span>// 2.5</span>
console.log(+'42'); // 42 (string to number) console.log(+true); // 1 console.log(+'abc'); // NaN console.log(42 + ''); // '42' (number to string) console.log({} + []); // '[object Object]' (both convert to strings) // The + operator console.log(1 + 2); // 3 (addition) console.log('1' + '2'); // '12' (string concatenation) console.log('1' + 2); // '12' (number converts to string) console.log(1 + '2'); // '12' (number converts to string) // But other operators convert strings to numbers console.log('5' - 2); // 3 console.log('5' * 2); // 10 console.log('5' / 2); // 2.5

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python is much stricter and doesn’t perform implicit type conversions.

Loop Peculiarities

for...in Loop Pitfalls

<span>const</span> <span>arr</span> <span>=</span> <span>[</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>];</span>
<span>arr</span><span>.</span><span>customProp</span> <span>=</span> <span>'</span><span>surprise</span><span>'</span><span>;</span>
<span>// for...in iterates over ALL enumerable properties, including inherited ones</span>
<span>for </span><span>(</span><span>const</span> <span>index</span> <span>in</span> <span>arr</span><span>)</span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>index</span><span>,</span> <span>arr</span><span>[</span><span>index</span><span>]);</span>
<span>}</span>
<span>// Outputs:</span>
<span>// '0' 1</span>
<span>// '1' 2</span>
<span>// '2' 3</span>
<span>// 'customProp' 'surprise'</span>
<span>// Use for...of for arrays (ES6+)</span>
<span>for </span><span>(</span><span>const</span> <span>value</span> <span>of</span> <span>arr</span><span>)</span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>value</span><span>);</span> <span>// Only outputs 1, 2, 3</span>
<span>}</span>
<span>const</span> <span>arr</span> <span>=</span> <span>[</span><span>1</span><span>,</span> <span>2</span><span>,</span> <span>3</span><span>];</span>
<span>arr</span><span>.</span><span>customProp</span> <span>=</span> <span>'</span><span>surprise</span><span>'</span><span>;</span>

<span>// for...in iterates over ALL enumerable properties, including inherited ones</span>
<span>for </span><span>(</span><span>const</span> <span>index</span> <span>in</span> <span>arr</span><span>)</span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>index</span><span>,</span> <span>arr</span><span>[</span><span>index</span><span>]);</span>
<span>}</span>
<span>// Outputs:</span>
<span>// '0' 1</span>
<span>// '1' 2</span>
<span>// '2' 3</span>
<span>// 'customProp' 'surprise'</span>

<span>// Use for...of for arrays (ES6+)</span>
<span>for </span><span>(</span><span>const</span> <span>value</span> <span>of</span> <span>arr</span><span>)</span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>value</span><span>);</span>  <span>// Only outputs 1, 2, 3</span>
<span>}</span>
const arr = [1, 2, 3]; arr.customProp = 'surprise'; // for...in iterates over ALL enumerable properties, including inherited ones for (const index in arr) { console.log(index, arr[index]); } // Outputs: // '0' 1 // '1' 2 // '2' 3 // 'customProp' 'surprise' // Use for...of for arrays (ES6+) for (const value of arr) { console.log(value); // Only outputs 1, 2, 3 }

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python’s for x in list iterates over values, similar to JavaScript’s for...of.

Object Iteration

<span>const</span> <span>person</span> <span>=</span> <span>{</span>
<span>name</span><span>:</span> <span>'</span><span>John</span><span>'</span><span>,</span>
<span>age</span><span>:</span> <span>30</span>
<span>};</span>
<span>// ES6+ ways to iterate over objects</span>
<span>Object</span><span>.</span><span>keys</span><span>(</span><span>person</span><span>).</span><span>forEach</span><span>(</span><span>key</span> <span>=></span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>key</span><span>,</span> <span>person</span><span>[</span><span>key</span><span>]);</span>
<span>});</span>
<span>Object</span><span>.</span><span>values</span><span>(</span><span>person</span><span>).</span><span>forEach</span><span>(</span><span>value</span> <span>=></span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>value</span><span>);</span>
<span>});</span>
<span>Object</span><span>.</span><span>entries</span><span>(</span><span>person</span><span>).</span><span>forEach</span><span>(([</span><span>key</span><span>,</span> <span>value</span><span>])</span> <span>=></span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>key</span><span>,</span> <span>value</span><span>);</span>
<span>});</span>
<span>const</span> <span>person</span> <span>=</span> <span>{</span>
    <span>name</span><span>:</span> <span>'</span><span>John</span><span>'</span><span>,</span>
    <span>age</span><span>:</span> <span>30</span>
<span>};</span>

<span>// ES6+ ways to iterate over objects</span>
<span>Object</span><span>.</span><span>keys</span><span>(</span><span>person</span><span>).</span><span>forEach</span><span>(</span><span>key</span> <span>=></span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>key</span><span>,</span> <span>person</span><span>[</span><span>key</span><span>]);</span>
<span>});</span>

<span>Object</span><span>.</span><span>values</span><span>(</span><span>person</span><span>).</span><span>forEach</span><span>(</span><span>value</span> <span>=></span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>value</span><span>);</span>
<span>});</span>

<span>Object</span><span>.</span><span>entries</span><span>(</span><span>person</span><span>).</span><span>forEach</span><span>(([</span><span>key</span><span>,</span> <span>value</span><span>])</span> <span>=></span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>key</span><span>,</span> <span>value</span><span>);</span>
<span>});</span>
const person = { name: 'John', age: 30 }; // ES6+ ways to iterate over objects Object.keys(person).forEach(key => { console.log(key, person[key]); }); Object.values(person).forEach(value => { console.log(value); }); Object.entries(person).forEach(([key, value]) => { console.log(key, value); });

Enter fullscreen mode Exit fullscreen mode

Python comparison: In Python, dict.items(), dict.keys(), and dict.values() provide similar functionality.

Date and Time Weirdness

<span>// Month is zero-indexed</span>
<span>const</span> <span>date</span> <span>=</span> <span>new</span> <span>Date</span><span>(</span><span>2023</span><span>,</span> <span>0</span><span>,</span> <span>15</span><span>);</span> <span>// January 15, 2023</span>
<span>// Date parsing is inconsistent across browsers</span>
<span>const</span> <span>parsed</span> <span>=</span> <span>new</span> <span>Date</span><span>(</span><span>'</span><span>2023-04-05</span><span>'</span><span>);</span> <span>// Different browsers might interpret differently</span>
<span>// Date math</span>
<span>const</span> <span>today</span> <span>=</span> <span>new</span> <span>Date</span><span>();</span>
<span>const</span> <span>tomorrow</span> <span>=</span> <span>new</span> <span>Date</span><span>(</span><span>today</span><span>);</span>
<span>tomorrow</span><span>.</span><span>setDate</span><span>(</span><span>today</span><span>.</span><span>getDate</span><span>()</span> <span>+</span> <span>1</span><span>);</span> <span>// Add one day</span>
<span>// Date to timestamp</span>
<span>const</span> <span>timestamp</span> <span>=</span> <span>today</span><span>.</span><span>getTime</span><span>();</span> <span>// Milliseconds since Jan 1, 1970</span>
<span>// Month is zero-indexed</span>
<span>const</span> <span>date</span> <span>=</span> <span>new</span> <span>Date</span><span>(</span><span>2023</span><span>,</span> <span>0</span><span>,</span> <span>15</span><span>);</span>  <span>// January 15, 2023</span>

<span>// Date parsing is inconsistent across browsers</span>
<span>const</span> <span>parsed</span> <span>=</span> <span>new</span> <span>Date</span><span>(</span><span>'</span><span>2023-04-05</span><span>'</span><span>);</span>  <span>// Different browsers might interpret differently</span>

<span>// Date math</span>
<span>const</span> <span>today</span> <span>=</span> <span>new</span> <span>Date</span><span>();</span>
<span>const</span> <span>tomorrow</span> <span>=</span> <span>new</span> <span>Date</span><span>(</span><span>today</span><span>);</span>
<span>tomorrow</span><span>.</span><span>setDate</span><span>(</span><span>today</span><span>.</span><span>getDate</span><span>()</span> <span>+</span> <span>1</span><span>);</span>  <span>// Add one day</span>

<span>// Date to timestamp</span>
<span>const</span> <span>timestamp</span> <span>=</span> <span>today</span><span>.</span><span>getTime</span><span>();</span>  <span>// Milliseconds since Jan 1, 1970</span>
// Month is zero-indexed const date = new Date(2023, 0, 15); // January 15, 2023 // Date parsing is inconsistent across browsers const parsed = new Date('2023-04-05'); // Different browsers might interpret differently // Date math const today = new Date(); const tomorrow = new Date(today); tomorrow.setDate(today.getDate() + 1); // Add one day // Date to timestamp const timestamp = today.getTime(); // Milliseconds since Jan 1, 1970

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python’s datetime module uses 1-indexed months and has more consistent parsing behavior.

The Module System

CommonJS (Node.js) vs. ES Modules

<span>// CommonJS (Node.js)</span>
<span>const</span> <span>fs</span> <span>=</span> <span>require</span><span>(</span><span>'</span><span>fs</span><span>'</span><span>);</span>
<span>module</span><span>.</span><span>exports</span> <span>=</span> <span>{</span> <span>myFunction</span> <span>};</span>
<span>// ES Modules (modern)</span>
<span>import</span> <span>fs</span> <span>from</span> <span>'</span><span>fs</span><span>'</span><span>;</span>
<span>export</span> <span>const</span> <span>myFunction</span> <span>=</span> <span>()</span> <span>=></span> <span>{};</span>
<span>// CommonJS (Node.js)</span>
<span>const</span> <span>fs</span> <span>=</span> <span>require</span><span>(</span><span>'</span><span>fs</span><span>'</span><span>);</span>
<span>module</span><span>.</span><span>exports</span> <span>=</span> <span>{</span> <span>myFunction</span> <span>};</span>

<span>// ES Modules (modern)</span>
<span>import</span> <span>fs</span> <span>from</span> <span>'</span><span>fs</span><span>'</span><span>;</span>
<span>export</span> <span>const</span> <span>myFunction</span> <span>=</span> <span>()</span> <span>=></span> <span>{};</span>
// CommonJS (Node.js) const fs = require('fs'); module.exports = { myFunction }; // ES Modules (modern) import fs from 'fs'; export const myFunction = () => {};

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python’s import system is more straightforward and consistent.

Common Gotchas for Python Developers

Semicolons

<span>// Semicolons are optional but recommended</span>
<span>const</span> <span>x</span> <span>=</span> <span>5</span><span>;</span> <span>// With semicolon</span>
<span>const</span> <span>y</span> <span>=</span> <span>10</span> <span>// Without semicolon</span>
<span>// Automatic Semicolon Insertion can cause bugs</span>
<span>// This returns undefined because of ASI</span>
<span>function</span> <span>bad</span><span>()</span> <span>{</span>
<span>return</span>
<span>{</span>
<span>value</span><span>:</span> <span>42</span>
<span>}</span>
<span>}</span>
<span>// Correct way</span>
<span>function</span> <span>good</span><span>()</span> <span>{</span>
<span>return</span> <span>{</span>
<span>value</span><span>:</span> <span>42</span>
<span>};</span>
<span>}</span>
<span>// Semicolons are optional but recommended</span>
<span>const</span> <span>x</span> <span>=</span> <span>5</span><span>;</span>  <span>// With semicolon</span>
<span>const</span> <span>y</span> <span>=</span> <span>10</span>  <span>// Without semicolon</span>

<span>// Automatic Semicolon Insertion can cause bugs</span>
<span>// This returns undefined because of ASI</span>
<span>function</span> <span>bad</span><span>()</span> <span>{</span>
    <span>return</span>
    <span>{</span>
        <span>value</span><span>:</span> <span>42</span>
    <span>}</span>
<span>}</span>

<span>// Correct way</span>
<span>function</span> <span>good</span><span>()</span> <span>{</span>
    <span>return</span> <span>{</span>
        <span>value</span><span>:</span> <span>42</span>
    <span>};</span>
<span>}</span>
// Semicolons are optional but recommended const x = 5; // With semicolon const y = 10 // Without semicolon // Automatic Semicolon Insertion can cause bugs // This returns undefined because of ASI function bad() { return { value: 42 } } // Correct way function good() { return { value: 42 }; }

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python uses indentation for blocks and doesn’t use semicolons.

Multiline Strings

<span>// Template literals for multiline (ES6+)</span>
<span>const</span> <span>multiline</span> <span>=</span> <span>`This is a multiline string in JavaScript`</span><span>;</span>
<span>// Old style concatenation</span>
<span>const</span> <span>oldMultiline</span> <span>=</span> <span>'</span><span>This is a </span><span>\n</span><span>'</span> <span>+</span>
<span>'</span><span>multiline string</span><span>\n</span><span>'</span> <span>+</span>
<span>'</span><span>in JavaScript</span><span>'</span><span>;</span>
<span>// Template literals for multiline (ES6+)</span>
<span>const</span> <span>multiline</span> <span>=</span> <span>`This is a multiline string in JavaScript`</span><span>;</span>

<span>// Old style concatenation</span>
<span>const</span> <span>oldMultiline</span> <span>=</span> <span>'</span><span>This is a </span><span>\n</span><span>'</span> <span>+</span>
                     <span>'</span><span>multiline string</span><span>\n</span><span>'</span> <span>+</span>
                     <span>'</span><span>in JavaScript</span><span>'</span><span>;</span>
// Template literals for multiline (ES6+) const multiline = `This is a multiline string in JavaScript`; // Old style concatenation const oldMultiline = 'This is a \n' + 'multiline string\n' + 'in JavaScript';

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python supports triple-quoted strings for multiline text.

Global Scope Leakage

<span>function</span> <span>leaky</span><span>()</span> <span>{</span>
<span>x</span> <span>=</span> <span>5</span><span>;</span> <span>// Without var/let/const, becomes global variable!</span>
<span>}</span>
<span>leaky</span><span>();</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>);</span> <span>// 5</span>
<span>function</span> <span>leaky</span><span>()</span> <span>{</span>
    <span>x</span> <span>=</span> <span>5</span><span>;</span>  <span>// Without var/let/const, becomes global variable!</span>
<span>}</span>

<span>leaky</span><span>();</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>x</span><span>);</span>  <span>// 5</span>
function leaky() { x = 5; // Without var/let/const, becomes global variable! } leaky(); console.log(x); // 5

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python doesn’t create globals by default when variables are assigned in functions.

Prototype Inheritance vs. Class-based

<span>// Old-style prototype inheritance</span>
<span>function</span> <span>Animal</span><span>(</span><span>name</span><span>)</span> <span>{</span>
<span>this</span><span>.</span><span>name</span> <span>=</span> <span>name</span><span>;</span>
<span>}</span>
<span>Animal</span><span>.</span><span>prototype</span><span>.</span><span>speak</span> <span>=</span> <span>function</span><span>()</span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>`</span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span> makes a noise.`</span><span>);</span>
<span>};</span>
<span>// Modern class syntax (syntactic sugar over prototypes)</span>
<span>class</span> <span>Animal</span> <span>{</span>
<span>constructor</span><span>(</span><span>name</span><span>)</span> <span>{</span>
<span>this</span><span>.</span><span>name</span> <span>=</span> <span>name</span><span>;</span>
<span>}</span>
<span>speak</span><span>()</span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>`</span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span> makes a noise.`</span><span>);</span>
<span>}</span>
<span>}</span>
<span>// Old-style prototype inheritance</span>
<span>function</span> <span>Animal</span><span>(</span><span>name</span><span>)</span> <span>{</span>
    <span>this</span><span>.</span><span>name</span> <span>=</span> <span>name</span><span>;</span>
<span>}</span>

<span>Animal</span><span>.</span><span>prototype</span><span>.</span><span>speak</span> <span>=</span> <span>function</span><span>()</span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>`</span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span> makes a noise.`</span><span>);</span>
<span>};</span>

<span>// Modern class syntax (syntactic sugar over prototypes)</span>
<span>class</span> <span>Animal</span> <span>{</span>
    <span>constructor</span><span>(</span><span>name</span><span>)</span> <span>{</span>
        <span>this</span><span>.</span><span>name</span> <span>=</span> <span>name</span><span>;</span>
    <span>}</span>

    <span>speak</span><span>()</span> <span>{</span>
        <span>console</span><span>.</span><span>log</span><span>(</span><span>`</span><span>${</span><span>this</span><span>.</span><span>name</span><span>}</span><span> makes a noise.`</span><span>);</span>
    <span>}</span>
<span>}</span>
// Old-style prototype inheritance function Animal(name) { this.name = name; } Animal.prototype.speak = function() { console.log(`${this.name} makes a noise.`); }; // Modern class syntax (syntactic sugar over prototypes) class Animal { constructor(name) { this.name = name; } speak() { console.log(`${this.name} makes a noise.`); } }

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python uses true class-based inheritance, not prototypes.

Event Loop and Callback Queue

<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>First</span><span>'</span><span>);</span>
<span>setTimeout</span><span>(()</span> <span>=></span> <span>{</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Third</span><span>'</span><span>);</span>
<span>},</span> <span>0</span><span>);</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Second</span><span>'</span><span>);</span>
<span>// Output:</span>
<span>// First</span>
<span>// Second</span>
<span>// Third</span>
<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>First</span><span>'</span><span>);</span>

<span>setTimeout</span><span>(()</span> <span>=></span> <span>{</span>
    <span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Third</span><span>'</span><span>);</span>
<span>},</span> <span>0</span><span>);</span>

<span>console</span><span>.</span><span>log</span><span>(</span><span>'</span><span>Second</span><span>'</span><span>);</span>

<span>// Output:</span>
<span>// First</span>
<span>// Second</span>
<span>// Third</span>
console.log('First'); setTimeout(() => { console.log('Third'); }, 0); console.log('Second'); // Output: // First // Second // Third

Enter fullscreen mode Exit fullscreen mode

Python comparison: Python’s execution is typically synchronous unless explicitly using async features.

Debugging Tips for Python Developers

  1. Use console.log() instead of print().
  2. Browser dev tools are your best friend (similar to Python’s pdb).
  3. Use typeof to check types: typeof 42'number'.
  4. Remember that objects and arrays are passed by reference.
  5. Array indexes out of bounds return undefined, not errors.
  6. Use === instead of == most of the time.
  7. Watch out for scope issues with var.
  8. Be careful with async code and callbacks.
  9. Remember that functions are first-class objects.
  10. Use ESLint to catch common mistakes.

原文链接:Why Is This Undefined? JavaScript Traps for Python Programmers

© 版权声明
THE END
喜欢就支持一下吧
点赞5 分享
To the path of timber, iron and steel will never regret bright spray of molten steel was abandoned.
为了走上成材的道路,钢铁决不惋惜璀璨的钢花被遗弃
评论 抢沙发

请登录后发表评论

    暂无评论内容