- Published on
Fundamentals of JavaScript for Frontend Development
- Authors

- Name
- Abdullayev Shatlyk
Type Coercion
Coercion - is when JavaScript automatically changes one type to another during operations—like mixing apples and oranges, but the code tries to make them work together. It can be helpful but sneaky, leading to surprises if you're not careful.
let result = 'Price: ' + 100 // Number 100 becomes a string, output: "Price: 100"
let sum = '5' - 2 // String "5" becomes a number, output: 3
NOTE
But: "5" + 2 gives "52," not 7. Learn more about it here
Scope
Scope is like a fence around your variables—it decides where they can be seen and used in your code. Without it, everything would be chaotic. There are three types of scope: global scope (available anywhere in the code - window object), function scope (inside a function only), and block scope (inside curly braces like in if statements, using let or const). This keeps your code organized and secure.
function calculateTax(price) {
let tax = price * 0.1 // This 'tax' is visible only inside this function
return tax
}
console.log(tax) // Error! Can't see 'tax' out here—it's scoped to the function
Closures
A closure is like a backpack 🎒 that a function carries, holding onto variables from its "home" (outer function) even after the home is gone. It's great for keeping data private, like a secret pocket.
function makeCounter() {
let count = 0 // The 'secret' in the backpack 🎒
return function () {
// Inner function with access to count
count++ // Changes the outer variable
return count
}
}
let counter = makeCounter()
console.log(counter()) // 1
console.log(counter()) // 2 (Remembers the last count!)
this keyword
this is like a pointer saying, "Me!"—it refers to the object that's currently running the code. It changes depending on how you call the function, which can be tricky at first, like a chameleon.
Example: In an object, 'this' means the object itself.
The value of this depends on how the function is called.
- If this is used in the global object, the value of this is
windowobject (but if strict mode is used, the value is undefined). - In most cases, the value of
thisis the object to the left of the dot (the left rule ofthis). - If a function is an arrow function, it ignores all the above rules and obtains the value of
thisfrom the lexical environment during its creation. - If
call,apply, orbindare used to create or call a function,thisinside the function is the object passed as an argument.
Example 1
let User = {
name: 'Alice',
greet: function () {
console.log('Hello, ' + this.name) // 'this' is User object
},
}
User.greet() // "Hello, Alice"
Example 2
const Person1 = {
name: 'Alice',
greet: function () {
console.log('Hello, ' + this.name)
},
}
const Person2 = {
name: 'Bob',
}
// change the context of `this` by binding the Person2 object
const greetPerson2 = Person1.greet.bind(Person2)
greetPerson2() // Output: Hello, Bob
Explanation:
- Person1 has a method
greetthat usesthis.name. bind(Person2)creates a new functiongreetPerson2wherethisis permanently set to Person2.- Calling
greetPerson2()uses Person2's context, printing "Hello, Bob".
Object-Oriented Programming in JavaScript
OOP is like building with Lego blocks: you create blueprints (classes or prototypes) for objects that can inherit traits, making code reusable. It's for organizing bigger projects.
Prototypes
Prototypes are like family trees—objects inherit methods (actions) from a parent prototype, saving space by sharing.
function Person(name) {
this.name = name // Unique to each person
}
Person.prototype.greet = function () {
// Shared action
return 'Hi, ' + this.name
}
let Nick = new Person('Nick')
console.log(Nick.greet()) // "Hi, Nick"
Arrow Functions vs Normal Functions
Arrow functions are shorthand versions of normal functions, like quick notes vs full letters. The big difference: arrows don't have their own this — they borrow from surroundings, which is handy in some spots but not others.
let obj = {
value: 10,
normal: function () {
setTimeout(function () {
console.log(this.value)
}, 100)
},
arrow: function () {
setTimeout(() => {
console.log(this.value)
}, 100)
},
}
console.log(obj.normal()) // Undefined — wrong 'this' context
console.log(obj.arrow()) // 10—borrows obj's 'this'
Promises
Promises are like "I Owe You" for code that takes time (async) — they promise a result later, either success (resolve) or fail (reject). Chain them with .then() for steps.
let promise = new Promise((resolve, reject) => {
console.log('thinking...')
setTimeout(() => {
return resolve('Done!')
}, 2000) // Wait 1 second
})
promise.then((result) => console.log(result)) // "Done!"
Summary
- Scope: Fences variables; global everywhere, function/local hidden; prevents messes.
- Closures: Functions remember outer stuff; like private backpacks; useful for states.
- 'this' Keyword: Points to current object; changes with call; watch in events.
- OOP: Blueprints with prototypes/classes; inherit to reuse; methods are actions.
- Arrow vs Normal: Arrows short, share 'this'; good for quick anon funcs.
- Promises: Handle waits; resolve/reject; chain for steps.