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
- Use
console.log()
instead ofprint()
. - Browser dev tools are your best friend (similar to Python’s pdb).
- Use
typeof
to check types:typeof 42
→'number'
. - Remember that objects and arrays are passed by reference.
- Array indexes out of bounds return
undefined
, not errors. - Use
===
instead of==
most of the time. - Watch out for scope issues with
var
. - Be careful with async code and callbacks.
- Remember that functions are first-class objects.
- Use ESLint to catch common mistakes.
原文链接:Why Is This Undefined? JavaScript Traps for Python Programmers
暂无评论内容