JavaScript / ES6+ Bootcamp Lesson 3 – JavaScript Functions, Arrow Functions and Callbacks

This lesson is probably the most important JavaScript lesson before React.

You already know the basic idea of functions from Ruby. The big shift is:

In JavaScript, a function is also a value.

Once that clicks, callbacks, map, filter, React event handlers, useEffect, promises, and Node.js APIs become much easier to understand.

1. Normal function

The traditional syntax is:

function add(a, b) {
return a + b;
}

Call it:

const result = add(10, 20);
console.log(result); // 30

Execution:

add(10, 20)
โ†“
a = 10
b = 20
โ†“
a + b
โ†“
30

Very similar to Ruby:

def add(a, b)
a + b
end

2. A function is a value

This is the important part.

function add(a, b) {
return a + b;
}

You can do:

const operation = add;

Now:

operation(10, 20); // 30

Notice that we wrote:

const operation = add;

not:

const operation = add();

These are completely different.

add

Means:

Give me the function itself.

add()

Means:

Execute the function now and give me its return value.

Example:

function add() {
return 30;
}
const a = add;
const b = add();
console.log(a); // function
console.log(b); // 30

This distinction is extremely important for React.


3. Function expression

A function can also be assigned to a variable:

const add = function(a, b) {
return a + b;
};

Now:

add(10, 20);

This is called a function expression.

Compare:

function add(a, b) {
return a + b;
}

with:

const add = function(a, b) {
return a + b;
};

Both create functions, but they are written differently.


4. Arrow functions

Modern JavaScript heavily uses arrow functions.

const add = (a, b) => {
return a + b;
};

Shorter:

const add = (a, b) => a + b;

These are roughly equivalent for simple use cases:

function add(a, b) {
return a + b;
}
const add = (a, b) => a + b;

But later we’ll learn an important difference involving this.


5. Arrow function syntax

Let’s break down:

const add = (a, b) => a + b;
const add
โ†“
variable
(a, b)
โ†“
parameters
=>
โ†“
arrow function
a + b
โ†“
implicit return

Because there are no { }, JavaScript automatically returns the expression.

So:

const add = (a, b) => a + b;

means:

const add = (a, b) => {
return a + b;
};

6. Parentheses rules

With multiple parameters:

const add = (a, b) => a + b;

With one parameter, parentheses can be omitted:

const square = n => n * n;

Equivalent:

const square = (n) => n * n;

With no parameters:

const greet = () => "Hello";

So you’ll commonly see:

() => ...
x => ...
(x, y) => ...

7. Explicit vs implicit return

This is important.

Explicit return

const add = (a, b) => {
return a + b;
};

Implicit return

const add = (a, b) => a + b;

But this:

const add = (a, b) => {
a + b;
};

returns:

undefined

Why?

Because once you use { }, you have a function body. JavaScript requires an explicit:

return

if you want to return a value.


8. Returning an object from an arrow function

This is a common syntax trap.

You might write:

const createUser = () => {
name: "John"
};

That does not return the object you expect.

Use parentheses:

const createUser = () => ({
name: "John"
});

Now:

createUser();
// { name: "John" }

You’ll see this frequently in React code.


9. Functions can receive functions

This is where callbacks begin.

Consider:

function execute(callback) {
callback();
}

We can call it:

execute(() => {
console.log("Hello");
});

Let’s slow this down.

The function:

() => {
console.log("Hello");
}

is passed as an argument to:

execute(...)

Inside execute:

function execute(callback) {
callback();
}

So:

execute(...)
|
| receives function
โ†“
callback
|
| callback()
โ†“
console.log("Hello")

That passed function is called a callback.


10. Why is it called a callback?

Because you’re essentially saying:

“Here is a function. Call it when you need to.”

Example:

function processUser(user, callback) {
console.log("Processing user:", user.name);
callback(user);
}

Usage:

processUser(
{ name: "John" },
(user) => {
console.log("Finished:", user.name);
}
);

The second argument is the callback.


11. Callbacks are NOT automatically asynchronous

This is very important.

Look at:

function execute(callback) {
console.log("A");
callback();
console.log("B");
}
execute(() => {
console.log("C");
});

Output:

A
C
B

Everything is synchronous.

A callback simply means:

a function passed to another function.

It does not mean asynchronous.


12. Asynchronous callback

Now:

setTimeout(() => {
console.log("C");
}, 1000);
console.log("A");

Output:

A
C

after approximately one second.

Here the callback is asynchronous because setTimeout schedules it to run later.

This distinction is critical:

callback
โ‰ 
async

A callback may be:

synchronous
or
asynchronous

13. Higher-order functions

A function that:

  • accepts a function as an argument, or
  • returns a function

is commonly called a higher-order function.

Example:

function execute(callback) {
callback();
}

execute is a higher-order function because it accepts a function.

Another example:

function createGreeter() {
return function() {
console.log("Hello");
};
}

createGreeter is also a higher-order function because it returns a function.


14. This explains map

Now something you’ll see constantly in React:

const numbers = [1, 2, 3];
const doubled = numbers.map(n => n * 2);

What is actually happening?

map receives a function:

n => n * 2

Conceptually:

numbers.map(callback)
โ†“
function(n) {
return n * 2;
}

For every element, map calls your callback.

Conceptually:

1 โ†’ callback(1) โ†’ 2
2 โ†’ callback(2) โ†’ 4
3 โ†’ callback(3) โ†’ 6

Result:

[2, 4, 6]

15. map with objects

This is extremely important for React.

const users = [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" }
];
const names = users.map(user => user.name);

The callback:

user => user.name

runs for every user.

Result:

["John", "Jane"]

You can think:

users
โ†“
map(callback)
โ†“
John โ†’ "John"
Jane โ†’ "Jane"
โ†“
["John", "Jane"]

16. filter

filter also accepts a callback.

const numbers = [1, 2, 3, 4, 5];
const result = numbers.filter(n => n > 2);

The callback returns a boolean:

1 โ†’ false
2 โ†’ false
3 โ†’ true
4 โ†’ true
5 โ†’ true

Result:

[3, 4, 5]

The pattern is:

array.filter(callback)

17. find

const users = [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" }
];
const user = users.find(user => user.id === 2);

The callback is:

user => user.id === 2

Result:

{ id: 2, name: "Jane" }

18. Why React uses callbacks everywhere

Consider:

<button onClick={() => console.log("Clicked")}>
Click me
</button>

You’re giving React a function:

() => console.log("Clicked")

You’re essentially saying:

“When the click happens, call this function.”

That is a callback.

Another example:

users.map(user => (
<div key={user.id}>
{user.name}
</div>
))

Again:

user => (...)

is a callback.

So when you see React code filled with arrow functions, don’t think:

“React magic.”

Think:

“JavaScript is passing functions around.”

That mental model is much more useful.


19. A very important React mistake

Compare:

<button onClick={handleClick}>

and:

<button onClick={handleClick()}>

These are not the same.

First

onClick={handleClick}

means:

Give React the function. React will call it when the event occurs.

Second

onClick={handleClick()}

means:

Call the function right now and give the result to React.

This is one of the most common beginner mistakes.

Again:

function reference
handleClick
โ†“
"Here is the function"
function call
handleClick()
โ†“
"Execute it now"

20. Function parameters are just variables

Look at:

function greet(name) {
console.log(name);
}

When you call:

greet("John");

JavaScript effectively does:

name = "John"

Similarly:

function execute(callback) {
callback();
}

When:

execute(myFunction);

conceptually:

callback = myFunction

Then:

callback();

calls it.

This is the key to understanding callbacks.


21. Callback with data

Callbacks can receive values too.

function getUser(callback) {
const user = {
id: 1,
name: "John"
};
callback(user);
}

Usage:

getUser(user => {
console.log(user.name);
});

Execution:

getUser()
โ†“
create user
โ†“
callback(user)
โ†“
user => console.log(user.name)

Output:

John

This pattern is foundational to asynchronous JavaScript.


๐Ÿง  Ruby developer comparison

You already know something conceptually similar in Ruby:

[1, 2, 3].map { |n| n * 2 }

JavaScript:

[1, 2, 3].map(n => n * 2);

Ruby:

users.map { |user| user[:name] }

JavaScript:

users.map(user => user.name);

The syntax is different, but the underlying idea is similar:

collection
โ†“
iterate
โ†“
execute supplied function for each item
โ†“
produce result

But don’t equate Ruby blocks and JavaScript callbacks completely. JavaScript functions are first-class values in a particularly explicit way, and the language’s treatment of closures, this, arguments and async execution differs.


Int. questions

Try these before checking the answers.

Q1

What’s the difference?

handleClick

vs

handleClick()

Q2

What does this return?

const add = (a, b) => a + b;

Q3

Why does this return undefined?

const add = (a, b) => {
a + b;
};

Q4

What is a callback?

Q5

Are callbacks always asynchronous?

Q6

Why is map considered a higher-order-function use case?

Q7

What does this produce?

const numbers = [1, 2, 3];
const result = numbers.map(n => n * 10);

Mini exercise

Predict the output:

function calculate(a, b, callback) {
const result = a + b;
callback(result);
}
calculate(10, 20, result => {
console.log(result);
});

Then trace this one:

function execute(callback) {
console.log("A");
callback();
console.log("B");
}
execute(() => {
console.log("C");
});

Expected order:

?
?
?

And finally:

const users = [
{ id: 1, name: "John", active: true },
{ id: 2, name: "Jane", active: false },
{ id: 3, name: "Mike", active: true }
];
const activeUsers = users.filter(user => user.active);
const names = activeUsers.map(user => user.name);
console.log(names);

Try to mentally execute it as:

users
โ†“
filter(callback)
โ†“
active users
โ†“
map(callback)
โ†“
names

What you should take away

At this point, you should have these mental models:

function โ†’ a value
function() โ†’ call the function
callback โ†’ function passed to another function
higher-order func โ†’ accepts/returns functions
arrow function โ†’ concise function syntax
map/filter/find โ†’ receive callbacks

The next lesson should build directly on this:

Lesson 4 – Arrays, map, filter, find, reduce, spread and rest, with lots of React-style examples. That lesson will make expressions like users.map(...) feel natural rather than mysterious.

JavaScript / ES6+ Bootcamp – Lesson 2

This lesson is important because JavaScript variable scope behaves differently enough from Ruby to cause bugs and int. confusion.

The four things to understand:

let
const
scope
hoisting

let, const, Scope and Hoisting

1. let vs const

Start with the simplest rule:

const name = "Abhilash";
let age = 40;

Use const when the variable should not be reassigned:

const name = "Abhilash";
// name = "John"; โŒ

Use let when reassignment is required:

let age = 40;
age = 41; // โœ…

Important: const does NOT make the value immutable

This is a very important JavaScript int. question.

const users = [];
users.push("John"); // โœ…

The array can be modified.

What cannot happen is:

users = ["Jane"]; // โŒ

Why?

Because const prevents reassignment of the variable, not mutation of the object.

Think:

const users
|
v
[ "John" ]

You cannot make users point somewhere else:

users โ”€โ”€โ”€โ”€โ”€Xโ”€โ”€โ”€โ”€> [ "Jane" ]

But you can modify the existing array:

users
|
v
["John", "Jane"]

The same applies to objects:

const user = {
name: "John"
};
user.name = "Jane"; // โœ…

But:

user = {}; // โŒ

Int. answer

const prevents reassignment, but it does not make objects or arrays immutable.


2. What is scope?

Scope simply means:

Where can this variable be accessed?

Example:

const name = "Abhilash";
function greet() {
console.log(name);
}
greet();

name is available inside greet() because functions can access variables from their outer scope.

But:

function greet() {
const message = "Hello";
}
console.log(message); // โŒ

message exists only inside the function.

Visualize:

Global Scope
โ”‚
โ”œโ”€โ”€ name
โ”‚
โ””โ”€โ”€ greet()
โ”‚
โ””โ”€โ”€ message

greet() can see name.

The outside cannot see message.


3. Block scope

This is where let and const become important.

A block is anything inside { }, such as:

if (...)
{
}

or:

for (...)
{
}

Example:

if (true) {
const message = "Hello";
console.log(message); // โœ…
}
console.log(message); // โŒ

message is block scoped.

Same with let:

if (true) {
let age = 40;
}
console.log(age); // โŒ

4. Why var is different

Historically JavaScript used:

var name = "John";

var does not have block scope.

Example:

if (true) {
var name = "John";
}
console.log(name); // John

That surprises many developers.

Compare:

if (true) {
let name = "John";
}
console.log(name); // โŒ

This is one major reason modern JavaScript prefers let and const.


5. Ruby comparison

You may initially think:

if true
name = "John"
end
puts name

Ruby’s local-variable behavior is different from JavaScript’s block scoping rules.

For JavaScript, remember:

const + let
โ†“
block scoped

and:

var
โ†“
function scoped

You don’t need to use var in modern code, but you must understand it when reading legacy JavaScript.


6. Nested scope

Scopes can be nested.

const country = "India";
function outer() {
const state = "Kerala";
function inner() {
const city = "Kochi";
console.log(country);
console.log(state);
console.log(city);
}
inner();
}

inner() can access:

country
state
city

because it can look outward through its scope chain.

But outer() cannot access city.

Visualize:

Global
โ”‚
โ”œโ”€โ”€ country
โ”‚
โ””โ”€โ”€ outer
โ”‚
โ”œโ”€โ”€ state
โ”‚
โ””โ”€โ”€ inner
โ”‚
โ””โ”€โ”€ city

JavaScript searches for variables from the current scope outward.

This is called the scope chain.


7. A very important example

Look carefully:

const name = "Abhilash";
function greet() {
const message = `Hello ${name}`;
console.log(message);
}
greet();

Inside greet():

name

is not declared locally.

JavaScript looks outward:

greet scope
โ†“
global scope
โ†“
find name

This behavior becomes extremely important when we learn closures.


8. What is hoisting?

Now we get to a classic int. topic.

JavaScript processes declarations before executing the code in the current scope.

This behavior is commonly called hoisting.

But don’t interpret it as JavaScript literally moving your code to the top. That’s a useful mental model, but the actual mechanics are more nuanced.

Start with a function declaration:

greet();
function greet() {
console.log("Hello");
}

This works.

Why?

Function declarations are available before their textual position.


9. var and hoisting

Consider:

console.log(name);
var name = "John";

You might expect an error.

Instead:

undefined

A useful mental model is:

var name;
console.log(name);
name = "John";

The declaration is available, but the assignment happens later.


10. let and const are different

Now:

console.log(name);
let name = "John";

This produces:

ReferenceError

And:

console.log(name);
const name = "John";

also produces:

ReferenceError

This is often explained using the Temporal Dead Zone (TDZ).


11. Temporal Dead Zone

For let and const, the variable exists in the scope before its declaration is executed, but you cannot access it before that point.

Example:

console.log(age); // โŒ
let age = 40;

The area between entering the scope and reaching the declaration is called the:

Temporal Dead Zone

You don’t need to memorize the implementation details yet. The int.-level mental model is:

var
โ†“
hoisted + initialized as undefined
let / const
โ†“
hoisted but inaccessible until declaration is reached

12. Function declarations vs function expressions

This becomes important when we get to callbacks.

This works:

greet();
function greet() {
console.log("Hello");
}

But this does not:

greet();
const greet = function() {
console.log("Hello");
};

And similarly:

greet();
const greet = () => {
console.log("Hello");
};

The second forms involve a const variable, so the TDZ applies.


13. A common int. trap

What does this print?

var x = 10;
if (true) {
var x = 20;
}
console.log(x);

Answer:

20

Because var is function scoped, not block scoped.

Now:

let x = 10;
if (true) {
let x = 20;
}
console.log(x);

Answer:

10

The inner x belongs to the block.

Visualize:

let x = 10
โ”‚
โ”œโ”€โ”€ if block
โ”‚ โ””โ”€โ”€ let x = 20
โ”‚
โ””โ”€โ”€ outside -> x is still 10

14. Shadowing

JavaScript allows an inner scope to define a variable with the same name.

const name = "Abhilash";
function test() {
const name = "John";
console.log(name);
}
test();
console.log(name);

Output:

John
Abhilash

The inner variable shadows the outer one.

This is perfectly valid, although unnecessary shadowing can make code harder to read.


15. Why this matters in React

Consider:

function UserList() {
const [users, setUsers] = useState([]);
if (users.length === 0) {
const message = "No users";
return <p>{message}</p>;
}
return (
<ul>
...
</ul>
);
}

message exists only inside that if block.

React code frequently contains nested blocks, callbacks and functions, so understanding scope prevents many bugs.


16. Scope + callbacks = important later

Consider:

function createCounter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}

Don’t worry about understanding every detail yet.

The interesting question is:

How can the returned function still access count after createCounter() has finished?

That question leads directly to:

closures.

And closures are one of the most important JavaScript concepts for React and Node.js.


Qn) Is it necessary to put semi colon in Javascript?

No, putting a semicolon (or colon) at the end of a line is not mandatory in ES6 (ECMAScript 2015) or modern JavaScript.

JavaScript uses a feature called Automatic Semicolon Insertion (ASI). This means the JavaScript engine automatically inserts semicolons where it thinks they are needed to run your code correctly.

โš ๏ธ The Rare Exception

While you can safely omit semicolons 99% of the time, there are rare cases where leaving them out can break your code. This usually happens if a line starts with a bracket [ or parenthesis (.

Example of a bug without semicolons:

const user = "Alice"
['a', 'b'].forEach(letter => console.log(letter))

The JavaScript engine reads this as a single continuous line: const user = "Alice"['a', 'b'].forEach(...), which throws an error.

Best Practice

Because of ASI, choosing to use semicolons is largely a matter of personal or team preference:

  • With semicolons: Safer for beginners, prevents accidental ASI bugs, and follows traditional coding styles.
  • Without semicolons: Keeps code looking clean, modern, and reduces visual clutter.

Most development teams use a tool like Prettier or ESLint to automatically format the code and handle semicolons for them.

Int. questions

Try answering these without looking back.

Q1

What is the difference between:

const user = {};

and:

let user = {};

Q2

Why does this work?

const users = [];
users.push("John");

even though users is declared with const?

Q3

What is the output?

let x = 10;
if (true) {
let x = 20;
}
console.log(x);

Q4

What is the output?

var x = 10;
if (true) {
var x = 20;
}
console.log(x);

Q5

What happens here?

console.log(name);
let name = "John";

Q6

Why does this work?

greet();
function greet() {
console.log("Hello");
}

but this doesn’t?

greet();
const greet = () => {
console.log("Hello");
};

Mini exercise

Predict the output before running:

const name = "Abhilash";
function outer() {
const name = "John";
if (true) {
const name = "Jane";
console.log(name);
}
console.log(name);
}
outer();
console.log(name);

Expected mental trace:

global name
โ†“
outer name
โ†“
if-block name

The most important thing from this lesson is to build the habit of asking:

Which scope does this variable belong to?

That question will help enormously when we reach closures, callbacks, useEffect, event handlers, and async JavaScript.

Next lesson: Functions in depth – function declarations, expressions, arrow functions, parameters, return values, callbacks, and higher-order functions.

Lesson 3: https://railsdrop.com/2024/12/04/javascript-es6-bootcamp-lesson-3-javascript-functions-arrow-functions-and-callbacks/

JavaScript / ES6+ Bootcamp – Lesson 1

The goal of this lesson is simple: understand what JavaScript is actually doing when you write basic code.

Coming from Ruby, you’ll notice that many concepts are similar, but JavaScript has some syntax and behavior that becomes important later in React and Node.js.

Variables, Values, Objects, Arrays, Functions and Return Values

1. Variables: let and const

In modern JavaScript, primarily use:

const name = "Abhilash";
let age = 40;

Think of them roughly like Ruby local variables:

name = "Abhilash"
age = 40

The difference is important:

const

The variable cannot be reassigned:

const name = "Abhilash";
name = "John"; // TypeError

let

The variable can be reassigned:

let age = 40;
age = 41;

What about var?

You’ll see:

var name = "Abhilash";

in older JavaScript code.

For modern JavaScript:

Use const by default.
Use let when reassignment is required.
Avoid var unless you're dealing with legacy code.

2. Everything starts with values

JavaScript variables hold values.

const name = "Abhilash";
const age = 40;
const active = true;

These values have types.

typeof name; // "string"
typeof age; // "number"
typeof active; // "boolean"

Some common types:

string
number
boolean
undefined
null
object
symbol
bigint

For now, focus on:

string
number
boolean
undefined
null
object

3. Arrays

An array stores multiple values.

const numbers = [10, 20, 30];

You can access them using an index:

numbers[0]; // 10
numbers[1]; // 20
numbers[2]; // 30

Just like Ruby:

numbers = [10, 20, 30]
numbers[0] # 10

JavaScript arrays are zero-indexed too.

Important

This:

const numbers = [10, 20, 30];

means numbers contains one array value.

It does not mean:

numbers = 10
20
30

Think:

numbers
|
v
[10, 20, 30]

4. Objects

JavaScript objects are heavily used in React and Node.

const user = {
id: 1,
name: "Abhilash",
active: true
};

You can access properties:

user.name; // "Abhilash"
user.id; // 1
user.active; // true

Ruby equivalent:

user = {
id: 1,
name: "Abhilash",
active: true
}
user[:name]

JavaScript also supports bracket notation:

user["name"];

This becomes useful when the property name is dynamic.


5. Arrays can contain objects

This is extremely common in React.

const users = [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" },
{ id: 3, name: "Mike" }
];

Visualize it:

users
|
v
[
{ id: 1, name: "John" },
{ id: 2, name: "Jane" },
{ id: 3, name: "Mike" }
]

Then:

users[0].name;

returns:

"John"

This structure is everywhere in frontend applications.


6. Functions

A JavaScript function can be written like:

function add(a, b) {
return a + b;
}

Call it:

const result = add(10, 20);
console.log(result); // 30

Ruby equivalent:

def add(a, b)
a + b
end
result = add(10, 20)

So far, very familiar.


7. The important idea: functions are values

This is one of the biggest concepts you need for React and Node.

In JavaScript:

function add(a, b) {
return a + b;
}

The function itself is a value.

You can store it:

const operation = add;

Now:

operation(10, 20);

returns:

30

Visualize:

add
|
v
function
operation
|
+------> same function

This is why JavaScript can pass functions around so easily.


8. Functions can return anything

A function can return a number:

function getAge() {
return 40;
}

A string:

function getName() {
return "Abhilash";
}

An object:

function getUser() {
return {
id: 1,
name: "John"
};
}

An array:

function getUsers() {
return [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" }
];
}

And importantly, a function can return another function:

function createGreeter() {
return function() {
console.log("Hello");
};
}

We’ll use this concept later when learning closures.


9. This explains useState

Now let’s return to the example that confused you:

const [users, setUsers] = useState([]);

Ignore React for a moment.

Imagine an ordinary function:

function useState(initialValue) {
return [
initialValue,
function setValue(value) {
console.log(value);
}
];
}

Now call:

const result = useState([]);

What does result contain?

Conceptually:

[
[],
setValueFunction
]

So:

const users = result[0];
const setUsers = result[1];

Now combine the two operations with destructuring:

const [users, setUsers] = result;

Therefore:

const [users, setUsers] = useState([]);

means:

1. Pass [] into useState
2. useState returns [value, function]
3. destructure that returned array
4. users gets element 0
5. setUsers gets element 1

This is a critical mental model.


10. Array destructuring

Let’s isolate the JavaScript feature.

const numbers = [10, 20];
const [a, b] = numbers;

Equivalent to:

const a = numbers[0];
const b = numbers[1];

You can even ignore values:

const [first, , third] = [10, 20, 30];
console.log(first); // 10
console.log(third); // 30

11. Object destructuring

There is another extremely common form:

const user = {
name: "John",
age: 30
};
const { name, age } = user;

Equivalent to:

const name = user.name;
const age = user.age;

So remember:

Array -> []
Object -> {}

Therefore:

const [a, b] = array;
const { name, age } = object;

This distinction is extremely important in React.


12. Arrow functions

Modern JavaScript frequently uses:

const add = (a, b) => {
return a + b;
};

Short form:

const add = (a, b) => a + b;

Equivalent roughly to:

function add(a, b) {
return a + b;
}

React code uses arrow functions constantly:

users.map(user => user.name);

Don’t worry about map yet. Just notice:

user => user.name

is a function.


13. Why callbacks matter

Consider:

function execute(callback) {
callback();
}

Then:

execute(() => {
console.log("Hello");
});

What’s happening?

execute()
|
| receives a function
v
callback
|
v
callback()
|
v
console.log("Hello")

The function is being passed as a value.

This is the foundation of callbacks.

We’ll go much deeper into this in a later lesson.


Ruby developer mental model

For now, keep these mappings in your head:

JavaScriptRuby
const x = 10x = 10
[]Array
{}Hash-like object
functiondef / Proc/Lambda concepts
returnreturn
obj.nameobj[:name] for Hash
array[0]array[0]
function as valueProc/lambda/block-like concept
arrow functionlambda-ish syntax, but not identical

The last row is deliberately approximate. JavaScript functions, arrow functions, Ruby blocks, Procs and lambdas are not interchangeable concepts. We’ll cover the differences properly.


๐ŸŽฏ Lesson 1 int. questions

Try answering these without looking back.

Question 1

What does this return?

const numbers = [10, 20, 30];
numbers[1];

Question 2

What is the difference between:

const user = {
name: "John"
};

and:

const users = [
{ name: "John" }
];

Question 3

What does this do?

const [a, b] = [10, 20];

Question 4

What does this return?

function getUser() {
return {
id: 1,
name: "John"
};
}

Question 5

What is stored in operation?

function add(a, b) {
return a + b;
}
const operation = add;

Small exercise

Without running it, predict the output:

function getUser() {
return [
{ id: 1, name: "John" },
{ id: 2, name: "Jane" }
];
}
const users = getUser();
const [firstUser, secondUser] = users;
console.log(firstUser.name);
console.log(secondUser.name);

Then try this variation:

const [firstUser] = getUser();
console.log(firstUser.name);

The key skill I’m looking for is not memorizing syntax. It’s being able to mentally trace:

function call
โ†“
return value
โ†“
array/object
โ†“
destructuring
โ†“
variables

Once that becomes natural, a lot of React code will stop looking mysterious.

Next lesson: let, const, scope, hoisting, and why JavaScript behaves differently from Ruby around variable scope.

Happy Learning! to be continued..