Photo by Irvan Smith on Unsplash
JavaScript Starter Guide for Python Developers
This is all the JavaScript you need to start web dev journey as a Python Dev
Introduction
This guide is designed to help Python developers quickly get up to speed with JavaScript (JS).
1. Variables and Data Types
JavaScript Example
var userArr = ['name1', 1, 'name3'];
console.log(typeof userArr[0]);
Key Points:
var
,let
, andconst
:var
: Function-scoped, prone to hoisting.let
: Block-scoped, recommended for mutable variables.const
: Block-scoped, for constants (values cannot be reassigned).
Prefer
let
overvar
.Dynamic Typing: Like Python, JavaScript is dynamically typed. However, JS has more quirks due to implicit type coercion.
Python Comparison
user_arr = ['name1', 1, 'name3']
print(type(user_arr[0])) # <class 'str'>
In Python, variable scope depends on indentation (function or global scope), and const
is not natively supported.
2. Primitives and Type Coercion
JavaScript Example
let xConst = '1';
let y = 1 + xConst; // Implicit type coercion
console.log(typeof xConst); // 'string'
console.table([xConst, y]);
Quirks:
JavaScript implicitly converts types (e.g., adding a number to a string results in string concatenation).
Use
console.table()
for debugging.
Python Comparison
x_const = '1'
y = 1 + int(x_const) # Explicit type conversion
print(type(x_const)) # <class 'str'>
Python requires explicit type conversions and avoids implicit coercion.
3. Arrays
JavaScript Example
let arr = [1, 2, 5];
arr.push({ name: 'aditya' });
console.log(typeof arr[3]); // 'object'
Key Points:
Flexible Types: Arrays can hold mixed types, unlike Python lists.
Methods: Use
.push()
to append elements (similar to Python’s.append()
).No native tuple equivalent.
Python Comparison
arr = [1, 2, 5]
arr.append({'name': 'aditya'})
print(type(arr[3])) # <class 'dict'>
4. Objects
JavaScript Example
let userObj = {
age: 2,
isAvailable: function() {
return 'yes';
}
};
console.log(Object.keys(userObj)); // ['age', 'isAvailable']
Key Points:
Versatile: Objects in JS are more dynamic and flexible than Python dictionaries.
Methods: You can define functions directly within objects.
Use
Object.keys()
to get property names.
Python Comparison
user_obj = {
'age': 2,
'is_available': lambda: 'yes'
}
print(list(user_obj.keys())) # ['age', 'is_available']
5. Loops and Iterations
JavaScript Example
for (let i = 0; i < userArr.length; i++) {
userArr[i] = userArr[i] + 1;
}
Python Comparison
for i in range(len(user_arr)):
user_arr[i] = user_arr[i] + 1
6. Functions
JavaScript Example
// Function Declaration
function add(a) {
return a[0] + a[1];
}
// Arrow Function
const sum = (n) => {
let output = 0;
for (let i = 0; i < n; i++) {
output += i;
}
return output;
};
Key Points:
Multiple ways to define functions:
function
,const
, andarrow
.Arrow functions do not bind their own
this
(lexicalthis
).
- Quirk: Functions can accept more arguments than required, and these arguments can be of any datatype (e.g., Object, Array, or a single variable) without throwing an error. Even if a function doesn’t require an argument, passing one won’t result in an error.
Python Comparison
def add(a):
return a[0] + a[1]
def sum(n):
return sum(range(n))
7. Equality Operators
JavaScript Example
console.log(1 == '1'); // true
console.log(1 === '1'); // false
true === 1 // false (boolean vs. number) |Loose Equality
null === undefined // false (different types) |Loose Equality
1 == [1] // true |Loose Equality
5 === 5 // true (both value and type are the same) |Strict Equality
5 === '5' // false (different types: number vs. string) |Strict Equality
```
### Key Points:
- **`==`**** vs ****`===`****:**
- `==` performs type coercion.
- `===` checks both value and type (strict equality).
### Python Comparison
Python has only strict equality:
```python
print(1 == '1') # False
8. Asynchronous Programming
Callbacks
JavaScript execution is single-threaded in nature. JavaScript’s power lies in callbacks and asynchronous programming, which can be confusing. Many modern APIs, functions, and libraries have built-in callbacks, which may feel unintuitive for Python developers.
function fetchData(callback) {
setTimeout(() => {
callback('Data received!');
}, 1000);
}
Note: Async programming in JavaScript doesn’t mean multi-threading but is a way to asynchronously run the code without waiting for the current operation to complete. This is particularly useful for database queries, I/O operations, API calls, etc.
Callback Hell
function fetchDataStep1(data, callback) {
console.log(`Step 1: Processing ${data}`);
setTimeout(() => {
callback(`${data} -> Step 1 done`);
}, 1000);
}
function fetchDataStep2(data, callback) {
console.log(`Step 2: Processing ${data}`);
setTimeout(() => {
callback(`${data} -> Step 2 done`);
}, 1000);
}
function fetchDataStep3(data, callback) {
console.log(`Step 3: Processing ${data}`);
setTimeout(() => {
callback(`${data} -> Step 3 done`);
}, 1000);
}
// Chained callbacks (callback hell)
fetchDataStep1("Initial data", (step1Result) => {
fetchDataStep2(step1Result, (step2Result) => {
fetchDataStep3(step2Result, (step3Result) => {
console.log(`Final Result: ${step3Result}`);
});
});
});
Though nested callbacks make the work done, it is very hard to read the logic, especially at debug time.
Promises - To Avoid Callback Hell
A promise represents a placeholder for a future value. It’s an object that will either resolve (success) or reject (failure) at some point in time. Promises help to manage asynchronous operations more elegantly, avoiding callback hell—a situation where multiple nested callbacks make code difficult to read and maintain.
Understand Callback Hell Example As Python Dev -
def fetch_data_step1(data, callback):
print(f"Step 1: Processing {data}")
callback(f"{data} -> Step 1 done")
def fetch_data_step2(data, callback):
print(f"Step 2: Processing {data}")
callback(f"{data} -> Step 2 done")
def fetch_data_step3(data, callback):
print(f"Step 3: Processing {data}")
callback(f"{data} -> Step 3 done")
# Chained callbacks
fetch_data_step1("Initial data", lambda step1_result:
fetch_data_step2(step1_result, lambda step2_result:
fetch_data_step3(step2_result, lambda step3_result:
print(f"Final Result: {step3_result}")
)
)
)
"""
OR (look at the below function with the same example but without using lambda )
"""
def fetch_data_step1(data, callback):
print(f"Step 1: Processing {data}")
data_send_to_callback = f"{data} -> Step 1 done"
callback(data_send_to_callback)
def fetch_data_step2(data, callback):
print(f"Step 2: Processing {data}")
data_send_to_callback = f"{data} -> Step 2 done"
callback(data_send_to_callback)
def fetch_data_step3(data, callback):
print(f"Step 3: Processing {data}")
data_send_to_callback = f"{data} -> Step 3 done"
callback(data_send_to_callback)
# Callback functions
def handle_step1_result(step1_result):
fetch_data_step2(step1_result, handle_step2_result)
def handle_step2_result(step2_result):
fetch_data_step3(step2_result, handle_step3_result)
def handle_step3_result(step3_result):
print(f"Final Result: {step3_result}")
# Start the process
fetch_data_step1("Initial data", handle_step1_result)
"""
[Output]:
Step 1: Processing Initial data
Step 2: Processing Initial data -> Step 1 done
Step 3: Processing Initial data -> Step 1 done -> Step 2 done
Final Result: Initial data -> Step 1 done -> Step 2 done -> Step 3 done
"""
While code it functional, this is hard to read and maintain due to the deeply nested structure. To fix this readability, use Promise
Promise Syntax -
function orderPizza() {
return new Promise((resolve) => {
setTimeout(() => {
resolve('Order Delivered');
}, 2000);
});
}
orderPizza()
.then((result) => console.log(result))
.catch((error) => console.error(error));
Explaining Using Callback Hell Example -
function fetchDataStep1(data) {
return new Promise((resolve) => {
console.log(`Step 1: Processing ${data}`);
resolve(`${data} -> Step 1 done`);
});
}
function fetchDataStep2(data) {
return new Promise((resolve) => {
console.log(`Step 2: Processing ${data}`);
resolve(`${data} -> Step 2 done`);
});
}
function fetchDataStep3(data) {
return new Promise((resolve) => {
console.log(`Step 3: Processing ${data}`);
resolve(`${data} -> Step 3 done`);
});
}
// Chained Promises
fetchDataStep1("Initial data")
.then(step1Result => fetchDataStep2(step1Result))
.then(step2Result => fetchDataStep3(step2Result))
.then(step3Result => {
console.log(`Final Result: ${step3Result}`);
});
/*
[output]:
Step 1: Processing Initial data
Step 2: Processing Initial data -> Step 1 done
Step 3: Processing Initial data -> Step 1 done -> Step 2 done
Final Result: Initial data -> Step 1 done -> Step 2 done -> Step 3 done
*/
Python Comparison
Python typically uses asyncio
for async tasks:
import asyncio
async def order_pizza():
await asyncio.sleep(2)
return 'Order Delivered'
asyncio.run(order_pizza())
9. Error Handling
JavaScript Example
try {
console.log(undeclaredVar);
} catch (error) {
console.error('An error occurred:', error);
}
Python Comparison
try:
print(undeclared_var)
except NameError as e:
print(f'An error occurred: {e}')
10. Event Loop Basics
JavaScript Example
console.log('Start');
setTimeout(() => {
console.log('Timeout');
}, 1000);
console.log('End');
Key Points:
JavaScript’s event loop handles asynchronous tasks.
Outputs: Start, End, Timeout.
Additional Quirks for Python Developers
No built-in integer division (
//
); useMath.floor(a / b)
.undefined
is similar to Python’sNone
.No
elif
; useelse if
.Semicolons are optional but recommended for consistency.
Prototype-based inheritance instead of class-based.
Modern JavaScript Practices
Use
const
by default.Prefer
let
overvar
.Use arrow functions for concise syntax.
Embrace
promises
andasync/await
for asynchronous code.Always use strict equality (
===
).