JavaScript (ES6+): Core programming language for front-end logic
Introduction to JavaScript (ES6+)
JavaScript (JS) is a programming language used to make web pages interactive. It enables
the dynamic manipulation of web content, allowing the creation of interactive websites, games,
applications, and more. JavaScript is the core language for front-end logic in web development.
It interacts with HTML (structure) and CSS (styling) to bring interactivity to web pages.
Why use JavaScript?
● Adds interactivity to web pages (e.g., form validation, pop-ups, dynamic content).
● Manipulates the DOM (Document Object Model) to dynamically update web content
without reloading the page.
● Allows handling of events like user clicks, form submissions, and mouse movements.
● Can be used for both front-end and back-end development (with Node.js).
● Supports modern features such as modules, promises, and async/await for handling
asynchronous code.
Basic Syntax in JavaScript (ES6+)
JavaScript syntax includes keywords, operators, data structures, control structures, and
functions. Let’s dive into the foundational aspects first.
Variables
Variables are used to store data values.
js
CopyEdit
let name = "John"; // Declares a block-scoped variable
const pi = 3.14159; // Declares a constant value
var age = 30; // Declares a function-scoped or globally scoped
variable
● let: Block-scoped, preferred for variable declarations.
● const: Immutable constant; its value cannot be reassigned.
● var: Function-scoped, avoid using in modern development due to scope issues.
Data Types
JavaScript has different types of values.
● Number: let num = 5;
● String: let str = "Hello";
● Boolean: let isActive = true;
● Object: let obj = { key: 'value' };
● Array: let arr = [1, 2, 3];
● Null: let empty = null;
● Undefined: let undef;
Operators
● Arithmetic: +, -, *, /, %
● Comparison: ==, ===, !=, !==, <, >, <=, >=
● Logical: &&, ||, !
Functions
Functions are blocks of code designed to perform a particular task. Functions are invoked or
called when needed.
Function Declaration:
js
CopyEdit
function greet(name) {
return `Hello, ${name}!`;
greet('Alice'); // "Hello, Alice!"
Arrow Functions (ES6):
js
CopyEdit
const add = (a, b) => a + b;
console.log(add(2, 3)); // 5
Control Flow
Control flow structures like if-else, for loops, and while loops control the logic of the program.
If-else Statements
js
CopyEdit
let age = 18;
if (age >= 18) {
console.log("You are an adult.");
} else {
console.log("You are not an adult.");
Switch Case
js
CopyEdit
let day = 2;
switch (day) {
case 1: console.log('Monday'); break;
case 2: console.log('Tuesday'); break;
default: console.log('Unknown Day');
Loops
● For Loop:
js
CopyEdit
for (let i = 0; i < 5; i++) {
console.log(i); // Output: 0, 1, 2, 3, 4
}
● While Loop:
js
CopyEdit
let i = 0;
while (i < 5) {
console.log(i);
i++;
Arrays and Array Methods
Arrays are ordered collections of values.
js
CopyEdit
let arr = [1, 2, 3, 4];
// Accessing elements
console.log(arr[0]); // 1
// Array Methods
arr.push(5); // Adds 5 to the end of the array
arr.pop(); // Removes the last element from the array
arr.shift(); // Removes the first element from the array
arr.unshift(0); // Adds 0 to the beginning of the array
arr.forEach(el => console.log(el)); // Iterates over the array
elements
Objects and Object-Oriented Concepts
Objects are collections of key-value pairs. JavaScript is object-based, and everything is an
object, including functions.
js
CopyEdit
let person = {
name: "Alice",
age: 25,
greet: function() {
return `Hello, my name is ${this.name}`;
};
console.log(person.greet()); // "Hello, my name is Alice"
ES6 Classes
Classes in JavaScript (introduced in ES6) are syntactic sugar for prototypes and are used to
create objects.
js
CopyEdit
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
greet() {
return `Hello, I am ${this.name}`;
const john = new Person("John", 30);
console.log(john.greet()); // "Hello, I am John"
DOM Manipulation
JavaScript is heavily used to manipulate HTML content dynamically via the DOM (Document
Object Model).
js
CopyEdit
// Select an element
let heading = document.getElementById('title');
// Change text content
heading.textContent = 'Welcome to JavaScript';
// Add a new class to the element
heading.classList.add('highlight');
Event Handling
JavaScript allows you to add interactive elements that respond to user input such as clicks,
typing, and more.
js
CopyEdit
// Select the button
const button = document.querySelector('#btn');
// Add click event listener
button.addEventListener('click', function() {
alert('Button clicked!');
});
Promises and Async/Await (Asynchronous JavaScript)
JavaScript can handle asynchronous tasks, such as fetching data from APIs, using Promises or
async/await.
Promises
js
CopyEdit
let promise = new Promise(function(resolve, reject) {
let success = true;
if (success) resolve('Success!');
else reject('Failed!');
});
promise.then(function(result) {
console.log(result); // Output: Success!
}).catch(function(error) {
console.log(error);
});
Async/Await
js
CopyEdit
async function fetchData() {
let response = await fetch('https://api.example.com/data');
let data = await response.json();
console.log(data);
}
fetchData();
Modules (ES6+)
JavaScript allows you to split your code into separate files called modules. This helps in
organizing and maintaining the codebase.
Exporting a module:
js
CopyEdit
// math.js
export function add(a, b) {
return a + b;
Importing a module:
js
CopyEdit
// main.js
import { add } from './math.js';
console.log(add(2, 3)); // Output: 5
Modern JavaScript Features (ES6+)
Template Literals
js
CopyEdit
let name = "John";
console.log(`Hello, ${name}!`); // Template literal
Destructuring
js
CopyEdit
let person = { name: 'Alice', age: 25 };
let { name, age } = person;
console.log(name, age); // "Alice", 25
Spread and Rest Operators
● Spread: Expands an array or object into individual elements.
js
CopyEdit
let arr = [1, 2, 3];
console.log(...arr); // Output: 1 2 3
● Rest: Combines individual elements into an array.
js
CopyEdit
function sum(...args) {
return args.reduce((acc, val) => acc + val, 0);
console.log(sum(1, 2, 3)); // Output: 6
Cheat Sheet Summary
Here’s a brief overview of the key concepts in modern JavaScript:
● Variables: let, const, var
● Data Types: Numbers, Strings, Arrays, Objects
● Functions: Declaration, Arrow Functions
● Loops: for, while, forEach
● Conditionals: if-else, switch
● Objects & Classes: Objects, ES6 Classes, Methods
● Array Methods: push, pop, map, filter
● DOM Manipulation: getElementById, querySelector, addEventListener
● Event Handling: click, submit, input
● Promises and Async/Await: Handling async operations
● Modules: import, export
● Template Literals: ${variable}
● Destructuring: Object and array destructuring
● Spread/Rest Operators: ...
By learning these concepts, you will have a strong understanding of JavaScript and can apply it
effectively to front-end web development, making your pages interactive and dynamic. Let me
know if you'd like to explore any concept further!
Let's go deeper into the remaining advanced concepts and some specialized features of
JavaScript that are often overlooked but essential for mastering the language.
1. Closures
A closure is a function that remembers its lexical environment even when the function is
executed outside that lexical environment. Closures allow for data encapsulation.
js
CopyEdit
function outerFunction(outerVariable) {
return function innerFunction(innerVariable) {
console.log(`Outer Variable: ${outerVariable}`);
console.log(`Inner Variable: ${innerVariable}`);
};
const newFunction = outerFunction("outside");
newFunction("inside");
// Output:
// Outer Variable: outside
// Inner Variable: inside
Closures are useful when creating private variables or functions.
2. IIFE (Immediately Invoked Function Expression)
An IIFE is a function that runs as soon as it is defined. It’s mainly used for encapsulating code to
avoid polluting the global scope.
js
CopyEdit
(function() {
console.log("This is an IIFE");
})();
3. this Keyword
The value of this depends on the execution context (where the function is invoked).
● Global Context: this refers to the global object (Window in the browser).
● Object Method: this refers to the object that called the method.
● Event Listeners: this refers to the element that received the event.
js
CopyEdit
const person = {
name: "Alice",
greet() {
console.log(this.name); // "Alice"
},
};
person.greet(); // "Alice"
4. Call, Apply, and Bind
These methods allow you to explicitly set this inside a function.
● call(): Calls a function with a given this value and arguments provided individually.
● apply(): Similar to call(), but the arguments are provided as an array.
● bind(): Returns a new function, where the this value is bound to the argument
passed.
js
CopyEdit
const person1 = { name: 'John' };
const person2 = { name: 'Alice' };
function sayHello(age) {
console.log(`Hello, I'm ${this.name} and I'm ${age} years old.`);
sayHello.call(person1, 25); // "Hello, I'm John and I'm 25 years
old."
sayHello.apply(person2, [30]); // "Hello, I'm Alice and I'm 30 years
old."
const boundFunction = sayHello.bind(person1);
boundFunction(28); // "Hello, I'm John and I'm 28 years old."
5. Prototypes and Inheritance
In JavaScript, objects inherit properties from their prototype. All JavaScript objects have a
prototype, and JavaScript uses prototypes to share methods and properties between objects.
js
CopyEdit
function Person(name) {
this.name = name;
Person.prototype.greet = function() {
console.log(`Hello, my name is ${this.name}`);
};
const person1 = new Person('Alice');
person1.greet(); // "Hello, my name is Alice"
ES6 Classes are essentially syntactic sugar over JavaScript's prototype-based inheritance.
6. Async Iteration (for await of)
Async Iteration allows us to loop over promises. This is very useful when working with async
functions that return iterables.
js
CopyEdit
async function* asyncGenerator() {
yield "First";
yield "Second";
yield "Third";
(async () => {
for await (const value of asyncGenerator()) {
console.log(value);
})();
7. Generators
Generators are a special type of function that can be paused and resumed. They are defined
using the function* syntax.
js
CopyEdit
function* generatorFunction() {
yield 'First';
yield 'Second';
yield 'Third';
const generator = generatorFunction();
console.log(generator.next().value); // "First"
console.log(generator.next().value); // "Second"
console.log(generator.next().value); // "Third"
8. Symbol Data Type
Symbols are a new primitive type in JavaScript that are unique and immutable. Symbols are
often used to create unique keys in objects.
js
CopyEdit
let sym1 = Symbol("identifier");
let sym2 = Symbol("identifier");
console.log(sym1 === sym2); // false (every Symbol is unique)
9. Map and Set
● Map: Stores key-value pairs where keys can be any data type (similar to objects but with
more flexibility).
● Set: Stores unique values of any type.
js
CopyEdit
// Map
let map = new Map();
map.set('name', 'Alice');
console.log(map.get('name')); // "Alice"
// Set
let set = new Set();
set.add(1);
set.add(2);
set.add(1); // Duplicate, won't be added again
console.log(set.size); // 2
10. WeakMap and WeakSet
● WeakMap: Similar to Map, but keys must be objects, and they are "weakly held,"
meaning if the object is garbage collected, the entry is removed.
● WeakSet: Similar to Set, but stores only objects, and they are also weakly held.
js
CopyEdit
let weakMap = new WeakMap();
let obj = {};
weakMap.set(obj, 'value');
obj = null; // The object can be garbage collected, removing it from
the WeakMap.
11. Event Loop and Async Programming
JavaScript is single-threaded. The event loop is responsible for managing the execution of
code, collecting events, and executing queued tasks.
The call stack runs synchronous code, while promises and asynchronous operations are
placed in the task queue (or microtask queue).
js
CopyEdit
console.log('Start');
setTimeout(() => {
console.log('Timeout'); // Executes after synchronous code is done
}, 0);
Promise.resolve().then(() => console.log('Promise')); // Executes
before setTimeout
console.log('End');
// Output:
// Start
// End
// Promise
// Timeout
12. Modules (ES Modules)
Modern JavaScript uses the module system to split code into manageable chunks. You can
import/export modules across files.
js
CopyEdit
// Export (module.js)
export const name = 'John';
export function greet() {
console.log('Hello');
// Import (main.js)
import { name, greet } from './module.js';
console.log(name); // "John"
greet(); // "Hello"
13. Nullish Coalescing Operator (??)
This operator is used to assign default values when a variable is null or undefined.
js
CopyEdit
let value = null;
let defaultValue = value ?? "default";
console.log(defaultValue); // "default"
14. Optional Chaining (?.)
The optional chaining operator (?.) allows you to safely access deeply nested object
properties without having to check each level manually.
js
CopyEdit
let user = { address: { city: 'New York' } };
console.log(user.address?.city); // "New York"
console.log(user.address?.zipcode); // undefined
15. Debouncing and Throttling
These techniques are useful for optimizing performance when an event (like scroll or resize) is
fired multiple times per second.
● Debouncing: Ensures a function is only called once after a delay.
js
CopyEdit
function debounce(func, delay) {
let timer;
return function() {
clearTimeout(timer);
timer = setTimeout(func, delay);
};
}
● Throttling: Ensures a function is called at most once in a specified time interval.
js
CopyEdit
function throttle(func, limit) {
let inThrottle;
return function() {
if (!inThrottle) {
func();
inThrottle = true;
setTimeout(() => inThrottle = false, limit);
};
Cheat Sheet Summary (Advanced Concepts):
● Closures: Functions that remember their lexical scope.
● IIFE: Immediately Invoked Function Expressions for encapsulation.
● this: Context-dependent keyword.
● Call, Apply, Bind: Methods to set this context explicitly.
● Prototypes: Shared methods and properties through inheritance.
● Generators: Functions that can be paused and resumed.
● Async Iteration: Using for await...of to loop through promises.
● Symbol: Unique and immutable identifiers.
● Map and Set: Data structures for storing key-value pairs and unique values.
● WeakMap and WeakSet: Similar to Map/Set but for objects that can be garbage
collected.
● Event Loop: Core of JavaScript's asynchronous behavior.
● Modules: Organizing code into separate files and importing/exporting functionality.
● Nullish Coalescing (??): Default assignment for null/undefined.
● Optional Chaining (?.): Safe property access.
● Debouncing and Throttling: Optimizing event handling.
These concepts should cover almost every corner of JavaScript, from basics to more advanced
topics. Let me know if you need further exploration into any of these areas!
Let's dive into a few additional advanced JavaScript concepts that are often considered
niche or highly specialized, but crucial for becoming a complete JavaScript master.
1. Memoization
Memoization is a technique to optimize function calls by caching results of expensive
computations. This can significantly improve performance in cases where the same function is
called repeatedly with the same arguments.
js
CopyEdit
function memoize(fn) {
const cache = {};
return function (...args) {
const key = JSON.stringify(args);
if (cache[key]) {
return cache[key];
} else {
const result = fn(...args);
cache[key] = result;
return result;
};
const factorial = memoize(function (n) {
if (n === 0) return 1;
return n * factorial(n - 1);
});
console.log(factorial(5)); // 120
console.log(factorial(5)); // Retrieved from cache
2. Functional Programming Concepts in JavaScript
Functional programming is a programming paradigm where functions are treated as first-class
citizens. JavaScript allows for various functional programming techniques.
● Pure Functions: Functions that do not have side effects and return the same result for
the same input.
● Higher-order Functions: Functions that take other functions as arguments or return
functions.
Example of higher-order functions:
js
CopyEdit
function map(array, func) {
const result = [];
for (let i = 0; i < array.length; i++) {
result.push(func(array[i]));
return result;
console.log(map([1, 2, 3], (x) => x * 2)); // [2, 4, 6]
3. Currying
Currying is a functional programming technique where a function with multiple arguments is
transformed into a sequence of functions, each taking a single argument.
js
CopyEdit
function curry(fn) {
return function curried(...args) {
if (args.length >= fn.length) {
return fn.apply(this, args);
} else {
return function (...nextArgs) {
return curried.apply(this, args.concat(nextArgs));
};
};
function sum(a, b, c) {
return a + b + c;
const curriedSum = curry(sum);
console.log(curriedSum(1)(2)(3)); // 6
4. Tail Call Optimization (TCO)
In recursive functions, Tail Call Optimization (TCO) allows the last call of a function to be
optimized and avoids growing the stack. This helps improve the performance of recursive
functions.
js
CopyEdit
function factorial(n, acc = 1) {
if (n === 0) return acc;
return factorial(n - 1, n * acc); // Tail call
console.log(factorial(5)); // 120
Not all JavaScript engines support TCO yet, but it’s a useful concept to be aware of.
5. Typed Arrays and Buffers
Typed Arrays provide a way to work with binary data directly in memory. These are especially
useful when working with file APIs, WebGL, or any low-level buffer manipulation.
js
CopyEdit
// Creating a buffer of 8 bytes
let buffer = new ArrayBuffer(8);
// Creating a typed array to work with the buffer
let view = new Uint8Array(buffer);
view[0] = 255; // Max value for a Uint8Array
console.log(view[0]); // 255
6. Promises with Promise.allSettled() and Promise.race()
While Promise.all() is widely used, there are a few more advanced Promise methods:
● Promise.allSettled(): Waits for all promises to settle (either resolve or reject) and
returns an array of the outcomes.
js
CopyEdit
const promises = [
Promise.resolve('Success'),
Promise.reject('Error'),
Promise.resolve('Another Success'),
];
Promise.allSettled(promises).then((results) =>
results.forEach((result) => console.log(result.status))
);
// Output:
// fulfilled
// rejected
// fulfilled
● Promise.race(): Returns the result of the first promise to settle (whether it resolves or
rejects).
js
CopyEdit
const promise1 = new Promise((resolve) => setTimeout(resolve, 500,
'One'));
const promise2 = new Promise((resolve) => setTimeout(resolve, 300,
'Two'));
Promise.race([promise1, promise2]).then((result) =>
console.log(result)); // "Two"
7. JavaScript Proxy and Reflect API
The Proxy object allows you to create a proxy for another object and define custom behavior for
fundamental operations (e.g., property lookup, assignment, function invocation).
js
CopyEdit
const target = {
message1: "hello",
message2: "everyone",
};
const handler = {
get: function (target, prop, receiver) {
if (prop === 'message1') {
return "proxy says hello";
return Reflect.get(...arguments);
},
};
const proxy = new Proxy(target, handler);
console.log(proxy.message1); // "proxy says hello"
console.log(proxy.message2); // "everyone"
Reflect provides built-in methods that mirror many proxy handlers, offering a default behavior
that you can enhance in a proxy.
8. Intl API (Internationalization)
The Intl API helps format numbers, dates, and strings according to different locales.
js
CopyEdit
const number = 1234567.89;
// Format number according to the German locale
console.log(new Intl.NumberFormat('de-DE').format(number)); //
"1.234.567,89"
// Format date
const date = new Date();
console.log(new Intl.DateTimeFormat('en-GB').format(date)); //
"28/03/2025"
9. WeakRef and FinalizationRegistry (ES2021)
WeakRef allows you to hold weak references to objects, and FinalizationRegistry allows you
to register a callback when an object is garbage collected. These are useful for managing
memory in advanced applications.
js
CopyEdit
let obj = { name: 'John' };
let weakRef = new WeakRef(obj);
obj = null; // The object can be garbage collected now
console.log(weakRef.deref()); // Might return undefined if GC has
occurred
const registry = new FinalizationRegistry((heldValue) => {
console.log(`${heldValue} was garbage collected`);
});
registry.register(obj, 'Object 1');
10. At() Method for Arrays and Strings
Introduced in ES2022, the at() method allows you to access array/string elements using both
positive and negative indices.
js
CopyEdit
let arr = [1, 2, 3, 4, 5];
console.log(arr.at(-1)); // 5 (last element)
console.log(arr.at(0)); // 1 (first element)
let str = 'Hello';
console.log(str.at(-1)); // 'o' (last character)
11. Top-Level Await
Starting in ES2022, you can use the await keyword at the top level of a module (without
wrapping it in an async function).
js
CopyEdit
const data = await fetch('https://api.example.com/data').then((res) =>
res.json());
console.log(data);
12. BigInt
BigInt is a new data type in JavaScript to represent integers beyond the safe integer limit for the
Number type (2^53 - 1).
js
CopyEdit
let bigNumber = 9007199254740991n;
console.log(bigNumber + 1n); // 9007199254740992n
console.log(bigNumber + 2n); // 9007199254740993n
13. Pattern Matching (Proposal)
Pattern matching is a proposed feature (still under development) that is similar to switch
statements, but designed for more complex matching.
js
CopyEdit
// Future JavaScript (example syntax)
match (value) {
when { a: 1, b } -> console.log(`Matched with b = ${b}`),
when [1, 2, 3] -> console.log('Matched an array'),
else -> console.log('Default case')
14. Private Class Fields and Methods (ES2022)
JavaScript now supports private fields and methods in classes using the # prefix.
js
CopyEdit
class MyClass {
#privateField = 42;
#privateMethod() {
return 'This is private';
}
publicMethod() {
return this.#privateMethod();
const instance = new MyClass();
console.log(instance.publicMethod()); // "This is private"
console.log(instance.#privateField); // SyntaxError: Private field
not accessible
15. Nullish Assignment (??=) and Logical Assignment Operators
In ES2021, you have nullish assignment and logical assignment operators to shorten
common assignment patterns.
js
CopyEdit
let x = null;
x ??= 10; // Only assigns 10 if x is null or undefined
console.log(x); // 10
let y = true;
y &&= false; // Logical AND assignment
console.log(y); // false
let z = false;
z ||= true; // Logical OR assignment
console.log(z); // true
Quirky Behaviors of JS
JavaScript is known for some "weird" behaviors that often puzzle
developers, especially due to its type coercion rules. Understanding
these oddities can make you more confident in debugging and writing
error-free code. Let’s dive into some of the most confusing and quirky
behaviors of JavaScript:
1. The Difference Between == and ===
● ==: Performs type coercion before comparison. This means it tries
to convert the types to be the same before comparing them.
● ===: Strict equality, meaning no type conversion takes place—both
the value and the type must be the same.
Examples:
js
CopyEdit
1 == '1'; // true (type coercion occurs)
1 === '1'; // false (strict comparison, different types)
null == undefined; // true (they're considered equal in non-strict
comparison)
null === undefined; // false (different types)
true == 1; // true (boolean `true` is coerced to number `1`)
false == 0; // true (boolean `false` is coerced to number `0`)
'0' == 0; // true (string `'0'` is coerced to number `0`)
2. Type Coercion
Type coercion is when JavaScript automatically converts one data type
to another, such as strings to numbers or booleans to numbers.
Examples:
js
CopyEdit
5 + '5'; // "55" (number 5 is coerced to string and concatenated)
'5' - 2; // 3 (string '5' is coerced to number)
true + true; // 2 (boolean `true` is coerced to 1)
'5' + true; // "5true" (true is coerced to string)
'5' * 2; // 10 (string '5' is coerced to number)
null + 1; // 1 (null is coerced to 0)
undefined + 1; // NaN (undefined is not a number)
3. Weird Truthy and Falsy Values
In JavaScript, some values are considered falsy (meaning they behave
like false in a boolean context) and others are truthy.
Falsy Values:
● false
● 0
● "" (empty string)
● null
● undefined
● NaN
Everything else is truthy, even empty objects ({}) and empty arrays
([]).
Examples:
js
CopyEdit
Boolean(0); // false
Boolean(''); // false
Boolean([]); // true (empty array is truthy)
Boolean({}); // true (empty object is truthy)
Boolean(null); // false
Boolean(undefined); // false
Boolean(NaN); // false
// Logical examples
if ([]) {
console.log("Empty array is truthy!"); // This will run
if ({}) {
console.log("Empty object is truthy!"); // This will run
4. NaN: Not-A-Number, but a Weird Number
NaN stands for "Not-A-Number," but it is of type number. It behaves
strangely because NaN is not equal to itself.
Examples:
js
CopyEdit
typeof NaN; // "number"
NaN === NaN; // false (NaN is never equal to anything, not even
itself)
isNaN('Hello'); // true ('Hello' is not a number)
isNaN(123); // false (123 is a number)
isNaN(NaN); // true
Number.isNaN(NaN); // true
Number.isNaN('Hello'); // false (more reliable than global `isNaN`)
5. Object Comparison
Objects are compared by reference in JavaScript, not by value. This
means that two distinct objects with the same properties are not
equal.
Examples:
js
CopyEdit
let obj1 = { name: 'Alice' };
let obj2 = { name: 'Alice' };
console.log(obj1 == obj2); // false (different objects in memory)
console.log(obj1 === obj2); // false (different objects in memory)
let obj3 = obj1;
console.log(obj1 == obj3); // true (both variables reference the
same object)
console.log(obj1 === obj3); // true (same reference)
6. Addition vs Concatenation Confusion
In JavaScript, the + operator is used for both addition (with numbers)
and concatenation (with strings), leading to confusing results if the
types aren't clear.
Examples:
js
CopyEdit
1 + 2; // 3 (addition)
'1' + 2; // "12" (string concatenation)
1 + '2' + 3; // "123" (first '1' + '2' concatenates, then '12' + 3 is
still concatenation)
1 + 2 + '3'; // "33" (first 1 + 2 adds, then '3' concatenates)
'10' - 5; // 5 (string '10' is coerced to number for subtraction)
7. The typeof Operator
The typeof operator in JavaScript can give some unexpected results.
Examples:
js
CopyEdit
typeof null; // "object" (this is actually a bug in
JavaScript)
typeof []; // "object" (arrays are a type of object)
typeof function() {}; // "function" (functions have their own type)
typeof NaN; // "number" (NaN is considered a number)
typeof undefined; // "undefined"
typeof 123; // "number"
typeof 'hello'; // "string"
8. Automatic Semicolon Insertion (ASI)
JavaScript automatically inserts semicolons at the end of certain
lines if they're omitted, which can lead to unexpected behavior.
Example:
js
CopyEdit
// You might expect this to return an object
let a =
b: 1
};
console.log(a); // undefined! (because JavaScript automatically
inserts a semicolon after `let a =`)
let b = {
c: 1
};
console.log(b); // { c: 1 } (works fine with proper formatting)
9. Void Operator
The void operator evaluates an expression but returns undefined.
Example:
js
CopyEdit
console.log(void 0); // undefined
console.log(void (0 + 1)); // undefined (expression is evaluated, but
result is ignored)
10. JavaScript Arrays Are Just Objects
Arrays in JavaScript are special kinds of objects with numbered keys,
which leads to some odd behavior.
Example:
js
CopyEdit
const arr = [1, 2, 3];
arr['foo'] = 'bar'; // You can assign properties like an object
console.log(arr.length); // 3 (length doesn't count 'foo')
console.log(arr.foo); // "bar" (accessing property like an object)
11. Function Hoisting
Function declarations are hoisted to the top of the scope, meaning you
can call the function before it is defined in the code. But function
expressions (when a function is assigned to a variable) are not
hoisted.
Example:
js
CopyEdit
foo(); // "Hello" (works because foo is hoisted)
function foo() {
console.log("Hello");
// Function expressions are not hoisted
bar(); // Uncaught TypeError: bar is not a function
var bar = function () {
console.log("Hi");
};
12. Global Object Leakage
If you forget to declare a variable using var, let, or const, it will
be automatically created as a global variable. This can cause
unexpected issues in larger codebases.
Example:
js
CopyEdit
function test() {
x = 5; // Forgot to declare 'x'
test();
console.log(x); // 5 (now 'x' is a global variable)
13. this Keyword Confusion
The value of this in JavaScript depends on how a function is called.
This can change depending on whether you're in strict mode, or whether
the function is called as a method, constructor, or standalone.
Examples:
js
CopyEdit
function test() {
console.log(this);
test(); // In the browser: 'window' (global object)
let obj = {
method: test,
};
obj.method(); // 'this' is obj
new test(); // 'this' is a new empty object created by the
constructor
14. Arguments Object
JavaScript functions have access to an arguments object, which is an
array-like object containing the arguments passed to the function.
However, the arguments object can behave strangely in ES6+ code,
especially with default parameters or arrow functions.
Example:
js
CopyEdit
function example(a, b) {
console.log(arguments[0]); // 1
console.log(arguments[1]); // 2
example(1, 2);
// With default parameters
function example2(a = 10) {
console.log(arguments[0]); // undefined (because default parameter
is used)
example2();
Conclusion
These quirky behaviors in JavaScript can seem strange or confusing,
but they can also be incredibly powerful if understood properly. By
mastering these behaviors, you'll be more confident when debugging,
writing robust code, and avoiding common pitfalls!