└── README.md
/README.md:
--------------------------------------------------------------------------------
1 | # 100 Common JavaScript Interview Questions in 2025
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | #### You can also find all 100 answers here 👉 [Devinterview.io - JavaScript](https://devinterview.io/questions/web-and-mobile-development/javascript-interview-questions)
11 |
12 |
13 |
14 | ## 1. What are the _data types_ present in JavaScript?
15 |
16 | JavaScript has **primitive** and **composite** data types.
17 |
18 | ### Primitive Data Types
19 |
20 | - **Boolean**: Represents logical values of **true** or **false**.
21 | - **Null**: Denotes the lack of a value.
22 |
23 | - **Undefined**: Indicates a variable that has been declared but has not been assigned a value.
24 |
25 | - **Number**: Represents numeric values, including integers and floats.
26 |
27 | - **BigInt**: Allows for representation of integers with arbitrary precision.
28 |
29 | - **String**: Encapsulates sequences of characters.
30 |
31 | - **Symbol** (ES6): Provides a unique, immutable value.
32 |
33 | ### Composite Data Types
34 |
35 | - **Object**: Represents a set of key-value pairs and is used for more complex data structures.
36 | - **Function**: A callable object that can be defined using regular function syntax or using the `new Function()` constructor (rarely used).
37 |
38 | ### Notable Characteristics
39 |
40 | - JavaScript is **dynamically-typed**, meaning the data type of a variable can change during the execution of a program.
41 | - **Data type coercion** can occur, where values are implicitly converted from one type to another in specific contexts, such as during comparisons.
42 | - Arithmetic operations, particularly when one of the operands is a string, can lead to **implicit type conversions**.
43 |
44 |
45 | ## 2. What is the difference between _null_ and _undefined_?
46 |
47 | While both **null** and **undefined** represent "no value" in JavaScript, they are distinct in their roles and origins.
48 |
49 | ### Origin and Context
50 |
51 | - **null** usually denotes an intentionally **absent** value, and developers can set a variable to null to signify the absence of an object or a value. For example, if an API call doesn't return data, you might set a variable to null.
52 |
53 | - **undefined** typically indicates a variable that has been declared but not yet been assigned a value, or a property that doesn't exist on an object.
54 |
55 | ### Variable Initialization and Assignment
56 |
57 | - Variables that haven't been assigned a value are `undefined` by default, unless explicitly set to `null`.
58 | ```javascript
59 | let foo; // undefined
60 | let bar = null; // null
61 | ```
62 |
63 | ### Function Arguments
64 |
65 | - When a function is called, and the parameter isn't provided or its value is not set, the parameter is `undefined`.
66 | - **null** would instead be an explicit value provided as an argument.
67 |
68 | ### Object Properties
69 |
70 | - If you try to access a property on an object that doesn't exist, the result is `undefined`.
71 | ```javascript
72 | let obj = {};
73 | console.log(obj.nonExistentProperty); // undefined
74 | ```
75 |
76 | - **Null** can be used to clear a property value in an object that was previously set.
77 | ```javascript
78 | let obj = { prop: 'value' };
79 | obj.prop = null;
80 | ```
81 |
82 | ### The Equality Operation
83 |
84 | - In JavaScript, **undefined** and **null** are treated as equal when using loose equality (==) but not strict equality (===).
85 |
86 | ### Use-Cases and Best Practices
87 |
88 | - When you initialize a variable and are not ready to assign a meaningful value, it's more common to use **undefined** instead of **null** to indicate that the value isn't there yet.
89 | - For example, if you declare a user object but don't have their details yet, you might keep it as `undefined`.
90 |
91 | ### Code Example
92 |
93 | Here is the JavaScript code:
94 |
95 | ```javascript
96 | let var1;
97 | let var2 = null;
98 |
99 | let object = {
100 | a: 1,
101 | b: undefined
102 | };
103 |
104 | function test(arg1, arg2) {
105 | console.log(arg1); // undefined: not provided
106 | console.log(arg2); // null: provided as such
107 | }
108 |
109 | function clearProperty(prop) {
110 | delete object[prop];
111 | }
112 |
113 | console.log(var1); // undefined
114 | console.log(var2); // null
115 | console.log(object.a); // 1
116 | console.log(object.b); // undefined
117 | console.log(object.c); // undefined
118 |
119 | test(); // Both arguments are undefined
120 | test(1, null); // arg1 is 1, arg2 is null
121 |
122 | clearProperty('b'); // Removes property 'b' from object
123 | console.log(object.b); // undefined: Property 'b' was removed, not set to null
124 | ```
125 |
126 |
127 | ## 3. How does JavaScript handle _type coercion_?
128 |
129 | **Type Coercion** in JavaScript refers to the automatic conversion of values from one data type to another.
130 |
131 | ### Explicit and Implicit Coercion
132 |
133 | - **Explicit**: Achieved through methods such as `parseInt()`, `Number()`, and `toString()`.
134 | - **Implicit**: Automatically occurs during operations or comparisons. For example, combining a string and a number in an addition results in the automatic conversion of the number to a string.
135 |
136 | ### Common Coercion Scenarios
137 |
138 | 1. **Arithmetic Operations**: Strings are coerced to numbers.
139 | - **Example**: `"5" - 3` evaluates to `2`, as the string is coerced to a number.
140 |
141 | 2. **Loose Equality (==)**: Data types are often modified for comparisons.
142 | - **Example**: `"4" == 4` is `true` due to string coercion before the comparison.
143 |
144 | 3. **Conditionals** (if and Ternary Operators): Truthiness or falsiness is determined.
145 | - **Example**: `if(1)` evaluates to `true` because `1` coerces to `true`.
146 |
147 | 4. **Logical Operators**: Non-boolean values are coerced to booleans.
148 | - **Example**: `"hello" && 0` evaluates to `0` because the truthy `"hello"` short-circuits the `&&` operation, and `0` coerces to `false`.
149 |
150 |
151 | ## 4. Explain the concept of _hoisting_ in JavaScript.
152 |
153 | **Hoisting** is a JavaScript mechanism that involves moving variable and function declarations to the top of their containing scope **during the compile phase**. However, the assignments to these variables or the definitions of functions remain in place.
154 |
155 | For instance, even though the call to `myFunction` appears before its definition, hoisting ensures that it doesn't cause an error.
156 |
157 | ### Hoisting in Action
158 |
159 | Here's a Code Example:
160 |
161 | ```javascript
162 | console.log(myVar); // Undefined
163 | var myVar = 5;
164 |
165 | console.log(myVar); // 5
166 |
167 | // The above code is equivalent to the following during the compile phase:
168 | // var myVar;
169 | // console.log(myVar);
170 | // myVar = 5;
171 |
172 | console.log(sayHello()); // "Hello, World!"
173 | function sayHello() {
174 | return "Hello, World!";
175 | }
176 |
177 | // The above code is equivalent to the following during the compile phase:
178 | // function sayHello() {
179 | // return "Hello, World!";
180 | // }
181 | // console.log(sayHello());
182 | ```
183 |
184 | ### Why Hoisting Matters
185 |
186 | Understanding hoisting can help you prevent certain unexpected behaviors in your code. For example, it can shed light on unexpected "undefined" values that might appear even after a variable is declared and initialized.
187 |
188 | #### Global Scope and Hoisting
189 |
190 | In the global scope, variables declared with `var` and functions are always hoisted to the top. For example:
191 |
192 | ```javascript
193 | // During the compile phase, the following global declarations are hoisted:
194 | // var globalVar;
195 | // function globalFunction() {}
196 |
197 | console.log(globalVar); // Undefined
198 | console.log(globalFunction()); // "Hello, Global!"
199 | var globalVar = "I am global Var!";
200 | function globalFunction() {
201 | return "Hello, Global!";
202 | }
203 | ```
204 |
205 | #### Local Scope and Hoisting
206 |
207 | Variables and functions declared in local scopes within functions are also hoisted to the top of their scope.
208 |
209 | Here's a Code Example:
210 |
211 | ```javascript
212 | function hoistingInLocalScope() {
213 | // These local declarations are hoisted during the compile phase:
214 | // var localVar;
215 | // function localFunction() {}
216 |
217 | console.log(localVar); // Undefined
218 | localVar = "I am a local var!";
219 | console.log(localFunction()); // "Hello, Local!"
220 |
221 | var localVar;
222 | function localFunction() {
223 | return "Hello, Local!";
224 | }
225 | }
226 | ```
227 |
228 | ### Best Practices
229 |
230 | To write clean, readable code, it's important to:
231 |
232 | - Declare variables at the top of your scripts or functions to avoid hoisting-related pitfalls.
233 | - Initialize variables before use, **regardless of hoisting**, to ensure predictable behavior.
234 |
235 | ### ES6 and Hoisting
236 |
237 | With the introduction of `let` and `const` in ES6, JavaScript's behavior has adapted. Variables declared using `let` and `const` are still hoisted, but unlike `var`, they are **not initialized**.
238 |
239 | Here's an Example:
240 |
241 | ```javascript
242 | console.log(myLetVar); // ReferenceError: Cannot access 'myLetVar' before initialization
243 | let myLetVar = 5;
244 | ```
245 |
246 | ### Constants and Hoisting
247 |
248 | `const` and `let` behave similarly when hoisted, but their difference lies in the fact that `const` must be assigned a value at the time of declaration, whereas `let` does not require an initial value.
249 |
250 | Here's an Example:
251 |
252 | ```javascript
253 | console.log(myConstVar); // ReferenceError: Cannot access 'myConstVar' before initialization
254 | const myConstVar = 10;
255 |
256 | console.log(myLetVar); // Undefined
257 | let myLetVar = 5;
258 | ```
259 |
260 |
261 | ## 5. What is the _scope_ in JavaScript?
262 |
263 | **Scope** defines the accessibility and lifetime of variables in a program. In JavaScript, there are two primary types: **Global Scope** and **Local Scope**.
264 |
265 | ### Global Scope
266 |
267 | Any variable declared **outside of a function** is in the global scope. These can be accessed from both within functions and from other script tags.
268 |
269 | #### Example: Global Scope
270 |
271 | Here is the JavaScript code:
272 |
273 | ```javascript
274 | let globalVar = 'I am global';
275 |
276 | function testScope() {
277 | console.log(globalVar); // Output: 'I am global'
278 | }
279 |
280 | testScope();
281 | console.log(globalVar); // Output: 'I am global'
282 | ```
283 |
284 | ### Local Scope
285 |
286 | Variables declared within a **function** (using `let` or `const` or prior to JavaScript ES6 with `var`) have local scope, meaning they are only accessible within that function.
287 |
288 | #### Example: Local Scope
289 |
290 | Here is the JavaScript code:
291 |
292 | ```javascript
293 | function testScope() {
294 | let localVar = 'I am local';
295 | console.log(localVar); // Output: 'I am local'
296 | }
297 |
298 | // This statement will throw an error because localVar is not defined outside the function scope
299 | // console.log(localVar);
300 | ```
301 |
302 | ### Block Scope
303 |
304 | Starting from **ES6**, JavaScript also supports block scope, where variables defined inside code blocks (denoted by `{}` such as loops or conditional statements) using `let` or `const` are accessible only within that block.
305 |
306 | #### Example: Block Scope
307 |
308 | Here is the JavaScript code:
309 |
310 | ```javascript
311 | function testScope() {
312 | let localVar = 'I am local';
313 | if (true) {
314 | let blockVar = 'I am local to this block';
315 | console.log(localVar, blockVar); // Both will be accessible
316 | }
317 | // This statement will throw an error because blockVar is not defined outside the block scope
318 | // console.log(blockVar);
319 | }
320 |
321 | testScope();
322 | ```
323 |
324 |
325 | ## 6. What is the difference between `==` and `===`?
326 |
327 | **Strict equality** (`===`) in JavaScript requires both value and type to match, testing for more specific conditions and reducing the likelihood of unexpected results.
328 |
329 | In contrast, the **abstract equality** comparison (`==`) can lead to type coercion, potentially causing counterintuitive outcomes.
330 |
331 | While both comparison modes test value equality, `===` ensures an additional match of data type.
332 |
333 | ### Illustrative Example: Abstract vs. Strict Equality
334 |
335 | - Abstract Equality:
336 | - `5 == '5'` evaluates to `true` because JavaScript converts the string to a number for comparison.
337 | - Strict Equality:
338 | - `5 === '5'` evaluates to `false` because the types are not the same.
339 |
340 | ### Key Considerations
341 |
342 | - **Type Safety**: `===` is safer as it avoids unwanted type conversions.
343 | - **Performance**: `===` can be faster, especially for simple comparisons, as it doesn't involve type coercion or additional checks.
344 | - **Clarity**: Favoring `===` can make your code clearer and more predictable.
345 |
346 | ### Common Best Practices
347 |
348 | - **Use Strict Equality by Default**: This approach minimizes unintended side effects.
349 | - **Consider Type Coercion Carefully**: In specific cases or with proven understanding, `==` can be suitable, but be cautious about potential confusion.
350 |
351 | ### Code Example: Equality Operators
352 |
353 | Here is the JavaScript code:
354 |
355 | ```javascript
356 | // Abstract equality
357 | console.log('5' == 5); // true
358 | console.log(null == undefined); // true
359 | console.log(0 == false); // true
360 |
361 | // Strict equality
362 | console.log('5' === 5); // false
363 | console.log(null === undefined); // false
364 | console.log(0 === false); // false
365 | ```
366 |
367 |
368 | ## 7. Describe _closure_ in JavaScript. Can you give an example?
369 |
370 | In JavaScript, **closures** enable a **function** to access its outer scope, retaining this access even after the parent function has finished executing. This mechanism provides a powerful tool for data encapsulation and privacy.
371 |
372 | ### Core Concept
373 |
374 | When a **function** is defined within another function, it maintains a reference to the variables from the outer function, even after the outer function has completed execution and its local variables are typically no longer accessible.
375 |
376 | ### Key Components
377 |
378 | 1. **Outer Function (Parent function)**: It contains the inner functions or closures.
379 | 2. **Inner Function (Closure)**: Defined within the parent function, it references variables from the outer function.
380 | 3. **Lexical Environment**: The context where the inner function is defined, encapsulating the scope it has access to.
381 |
382 | ### Example: Password Generator
383 |
384 | Consider a simple scenario of a function in charge of generating a secret password:
385 |
386 | 1. The outer function, `generatePassword`, defines a local variable, `password` and returns an inner function `getPassword`.
387 | 2. The inner function, `getPassword`, has exclusive access to the `password` variable even after `generatePassword` has executed.
388 |
389 | Here is the JavaScript code:
390 |
391 | ```javascript
392 | function generatePassword() {
393 | let password = '';
394 | const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
395 | const passwordLength = 8;
396 | for(let i = 0; i < passwordLength; i++) {
397 | password += characters.charAt(Math.floor(Math.random() * characters.length));
398 | }
399 |
400 | return function getPassword() {
401 | return password;
402 | };
403 | }
404 |
405 | const getPassword = generatePassword();
406 |
407 | console.log(getPassword()); // Outputs the generated password.
408 | ```
409 |
410 | In this example, `getPassword` still has access to the `password` variable after the `generatePassword` function has completed, thanks to the closure mechanism.
411 |
412 | ### Application
413 |
414 | - **Data Privacy**: JavaScript design patterns like the Module and Revealing Module Patterns use closures to keep data private.
415 |
416 | - **Timeouts and Event Handlers**: Closures help preserve the surrounding context in asynchronous operations such as `setTimeout` and event handlers.
417 |
418 | ### Pitfalls to Avoid
419 |
420 | - **Memory Leakage**: If not used carefully, closures can cause memory leaks, as the outer function's variables continue to live in memory because of the closure link.
421 | - **Stale Data**: Be mindful of shared variables that might change after a closure has been defined, leading to unexpected behavior.
422 |
423 | ### Browser Compatibility
424 |
425 | The concept of closures is a fundamental aspect of the JavaScript language and is supported by all modern browsers and environments.
426 |
427 |
428 | ## 8. What is the '_this_ keyword' and how does its context change?
429 |
430 | In JavaScript, the context of **`this`** refers to the execution context, typically an object that owns the function where `this` is used.
431 |
432 | ### 'this' in the Global Scope
433 |
434 | In **non-strict** mode, `this` in the global scope refers to the `window` object. In **strict** mode, `this` is `undefined`.
435 |
436 | ### 'this' in Functions
437 |
438 | In **non-arrow functions**, the value of `this` depends on how the function is **invoked**. When invoked:
439 |
440 | - As a method of an object: `this` is the object.
441 | - Alone: In a browser, `this` is `window` or `global` in Node.js. In strict mode, it's `undefined`.
442 | - With `call`, `apply`, or `bind`: `this` is explicitly set.
443 | - As a constructor (with `new`): `this` is the newly created object.
444 |
445 | ### 'this' in Arrow Functions
446 |
447 | Arrow functions have a **fixed context** for `this` defined at **function creation** and are not changed by how they are invoked.
448 |
449 | - They do **not have** their own `this`.
450 | - They use the `this` from their surrounding lexical context (the enclosing function or global context).
451 |
452 | ### Code Example: Global Context
453 |
454 | Here is the JavaScript code:
455 |
456 | ```javascript
457 | // Main
458 | let globalVar = 10;
459 |
460 | function globalFunction() {
461 | console.log('Global this: ', this.globalVar);
462 | console.log('Global this in strict mode: ', this);
463 | }
464 |
465 | globalFunction(); // Output: 10, window or undefined (in strict mode)
466 |
467 | // In Node.js, it will be different, because "window" is not defined. But "this" will refer to the global object.
468 | ```
469 |
470 |
471 | ## 9. What are _arrow functions_ and how do they differ from regular functions?
472 |
473 | Let's look at the key features of **arrow functions** and how they differ from traditional functions in JavaScript.
474 |
475 | ### Arrow Functions: Key Features
476 |
477 | - **Concise Syntax**:
478 | - Especially useful for short, one-liner functions.
479 | - No need for `function` keyword or **braces** if there's a single expression.
480 |
481 | - **Implicit Return**:
482 | - When there's no explicit `{ return ... ;}` statement, arrow functions return the result of the single expression inside.
483 |
484 | - **`this` Binding**:
485 | - Does not have its **own `this`**. It's "inherited" from the surrounding (lexical) context. This feature is known as '**lexical scoping**'.
486 |
487 | ### Code Example: Standard Function vs. Arrow Function
488 |
489 | Here is the JavaScript code:
490 |
491 | ```javascript
492 | // Standard Function
493 | function greet(name) {
494 | return "Hello, " + name + "!";
495 | }
496 |
497 | // Arrow Function
498 | const greetArrow = name => "Hello, " + name + "!";
499 | ```
500 |
501 | In the code above, `greet` is a standard function, while `greetArrow` is an arrow function, showcasing the difference in syntax and required keywords.
502 |
503 | ### When to Use Arrow Functions
504 |
505 | - **Event Handlers**: Ideal for concise, inline event handling, where `this` context can be inherited from the lexical scope.
506 |
507 | - **Callback Functions**: Useful for array methods like `map`, `filter`, and `reduce`.
508 |
509 | - **Avoidance of `this` Redefinition**: When you want to maintain the surrounding context of `this` and avoid unintended redefinition.
510 |
511 | ### Code Example: Arrow Function and `this` Context
512 |
513 | Here is the JavaScript code:
514 |
515 | ```javascript
516 | // Using traditional functions
517 | document.getElementById('myButton').onclick = function() {
518 | console.log('Button clicked:', this); // Refers to the button element
519 | };
520 |
521 | // Using arrow functions
522 | document.getElementById('myButton').onclick = () => {
523 | console.log('Button clicked:', this); // Refers to the global/window object
524 | };
525 | ```
526 |
527 | In the arrow function example, the context of `this` does not refer to the button element, but to the global `window` object, because arrow functions do not have their own binding of `this`. Instead, they inherit `this` from their lexical scope, which in this case is the global context.
528 |
529 |
530 | ## 10. What are _template literals_ in JavaScript?
531 |
532 | **Template literals** are a feature in modern JavaScript versions that offer a more flexible and readable way to work with strings. They are often referred to as "template strings".
533 |
534 | ### Key Features
535 |
536 | - **Multiline Text**: Template literals support multiline strings without requiring escape characters or string concatenation with a `+` sign.
537 | - **String Interpolation**: They enable the seamless embedding of JavaScript expressions within strings, using `${}`.
538 |
539 | ### Syntax
540 |
541 | - **Single Versus Double Quotes**: For template literals, use backticks (\`) instead of single quotes ('') or double quotes ("").
542 | - **Placeholder**: The `${expression}` placeholder within the backticks allows for variable and expression injection.
543 |
544 | ### Example:
545 |
546 | ```javascript
547 | let name = "John";
548 | let message = `Hi ${name}!`;
549 |
550 | console.log(message); // Output: "Hi John!"
551 | ```
552 |
553 | ### Benefits
554 |
555 | - **Readability**: They can make code more understandable, especially when dealing with longer or complex strings, by keeping content closer to its intention.
556 | - **Interpolation & Expression**: Template literals reduce verbosity and rendering logic when integrating dynamic data.
557 |
558 | ### Code Example: Multiline Text and String Interpolation
559 |
560 | ```javascript
561 | // Regular String
562 | let poem = "Roses are red,\nViolets are blue,\nSugar is sweet,\nAnd so are you.";
563 |
564 | // Template Literal
565 | let poemTemplate = `
566 | Roses are red,
567 | Violets are blue,
568 | Sugar is sweet,
569 | And so are you.
570 | `;
571 | ```
572 |
573 | ### Browser Compatibility Concerns
574 |
575 | Template literals are universally supported in modern browsers and are now considered a **core JavaScript feature**. However, they may not work in older browsers such as Internet Explorer without transpilation or polyfilling.
576 |
577 |
578 | ## 11. What is a _higher-order function_ in JavaScript?
579 |
580 | A **higher-order function** in JavaScript is a function that can take other functions as arguments or can return functions. This feature enables functional programming paradigms such as `map`, `reduce`, and `filter`. Higher-order functions offer versatility and modularity, fostering streamlined, efficient code.
581 |
582 | ### Key Characteristics
583 |
584 | - **First-class functions**: Functions in JavaScript are considered first-class, meaning they are a legitimate data type and can be treated like any other value, including being assigned to variables, stored in data structures, or returned from other functions.
585 |
586 | - **Closure support**: Due to closures, a higher-order function can transport not just the enclosed data within the function definition, but also the lexical environment in which that data resides.
587 |
588 | - **Dynamic code**: Because JavaScript allows functions to be dynamically constructed and named, they can be dynamically passed to higher-order functions.
589 |
590 | ### Practical Applications
591 |
592 | - **Callback Execution**: Functions like `setTimeout` and `addEventListener` take a function as an argument and are thus higher-order.
593 |
594 | - **Event Handling**: Many event-driven systems leverage higher-order functions for tasks such as event subscription and emission.
595 |
596 | - **Iterative Operations**: The `map`, `filter`, and `reduce` functions in JavaScript operate on arrays and require functions to be passed, making them higher-order.
597 |
598 | - **Code Abstraction**: Higher-order functions enable the encapsulation of repetitive tasks, promoting cleaner, more readable code.
599 |
600 | ### Code Example: Higher-order Functions
601 |
602 | Here is the JavaScript code:
603 |
604 | ```javascript
605 | // Simple higher-order function
606 | function multiplier(factor) {
607 | return function(num) {
608 | return num * factor;
609 | };
610 | }
611 |
612 | // Invoke a higher-order function
613 | const twice = multiplier(2);
614 | console.log(twice(5)); // Output: 10
615 |
616 | // Functional programming with higher-order functions
617 | const numbers = [1, 2, 3, 4, 5];
618 | const doubled = numbers.map(multiplier(2)); // [2, 4, 6, 8, 10]
619 | const tripled = numbers.map(multiplier(3)); // [3, 6, 9, 12, 15]
620 | ```
621 |
622 |
623 | ## 12. Can functions be assigned as values to variables in JavaScript?
624 |
625 | Yes, **JavaScript** supports first-class functions, meaning **functions can be treated as variables** and then assigned to other variables or passed as arguments to other functions.
626 |
627 | Functions defined as regular functions or arrow functions are both first-class in JavaScript.
628 |
629 | ### Practical Code Example
630 |
631 | Here is the JavaScript code:
632 |
633 | ```javascript
634 | // Define a function
635 | function greet() {
636 | console.log('Hello!');
637 | }
638 |
639 | // Assign the function to a variable
640 | let sayHello = greet;
641 |
642 | // Call the function through the variable
643 | sayHello(); // Output: "Hello!"
644 |
645 | // Reassign the variable to a new function
646 | sayHello = function() {
647 | console.log('Bonjour!');
648 | };
649 |
650 | // Call it again to see the new behavior
651 | sayHello(); // Output: "Bonjour!"
652 | ```
653 |
654 | ### Practical Use Cases
655 |
656 | - **Callbacks**: Functions can be passed as parameters to other functions.
657 |
658 | - **Event Handling**: In web development, functions define how to respond to specific events, and these functions are often attached to event listeners.
659 |
660 | - **Modular Development**: In programming patterns like the Module pattern, functions are defined within a scope and then returned, similar to variables.
661 |
662 | - **Higher-Order Functions**: These functions operate on other functions, taking them as arguments or returning them, and are an essential part of many modern JavaScript libraries and frameworks.
663 |
664 |
665 | ## 13. How do _functional programming_ concepts apply in JavaScript?
666 |
667 | **Functional Programming** (FP) concepts in JavaScript are a direct result of the language's first-class functions. Key FP principles, such as immutability, pure functions, and **declarative** style, play a crucial role.
668 |
669 | ### Core Concepts
670 |
671 | #### First-Class Functions and Higher-Order Functions
672 |
673 | JavaScript treats functions as first-class citizens, allowing them to be assigned to variables, passed as parameters, and returned from other functions. This feature is foundational to FP in the language.
674 |
675 | #### Code Example:
676 |
677 | Here is the JavaScript code:
678 |
679 | ```javascript
680 | const sayHello = () => console.log('Hello!');
681 | const runFunction = (func) => func();
682 |
683 | runFunction(sayHello); // Output: "Hello!"
684 | ```
685 |
686 |
687 | ## 14. What are _IIFEs_ (Immediately Invoked Function Expressions)?
688 |
689 | The **Immediately Invoked Function Expression** (IIFE) design pattern employs an anonymous function that gets executed promptly after its definition.
690 |
691 | Key characteristics of IIFEs include localized variable scopes and immediate activation upon interpreter parsing.
692 |
693 | ### Code Example: IIFE
694 |
695 | Here is the JavaScript code:
696 |
697 | ```javascript
698 | (function(){
699 | var foo = 'bar';
700 | console.log(foo);
701 | })();
702 | ```
703 |
704 | In this example, the function is enclosed within parentheses, ensuring the enclosed function is evaluated as an expression. Subsequently, it is invoked with a trailing pair of parentheses.
705 |
706 | ### Core Functions of IIFE
707 |
708 | 1. **Encapsulation**: Through lexical scoping, IIFEs safeguard variables from leaking into the global scope. This, in turn, averts unintended variable tampering in the global context.
709 |
710 | 2. **Data Hiding**: Internal functions or data can be hidden from external access, providing a mechanism for information concealment and access control.
711 |
712 | 3. **Initialization**: The IIFE structure is ideal for setting up initial conditions, like binding events or pre-processing data.
713 |
714 | ### Use Cases
715 |
716 | - **Avoiding Variable Pollution**: When interfacing with libraries or inserting code snippets, IIFEs prevent global scope pollution.
717 |
718 | - **Module Patterns**: IIFEs, in combination with **closures**, lay the groundwork for modular code organization by shielding private variables and functions.
719 |
720 | ### Modern Alternatives
721 |
722 | With the introduction of ES6 and its `let` and `const` declarations, as well as block-scoped lexical environments, the necessity of IIFEs has reduced. Additionally, **arrow functions** provide a more concise method for defining immediately invoked functions.
723 |
724 | ### IIFE Variants
725 |
726 | 1. **Parentheses Invocation**: A pair of parentheses immediately invoke the enclosed function. While this approach is more extensive, it's devoid of self-documenting advantages.
727 | ```javascript
728 | (function(){
729 | console.log('Invoked!');
730 | })();
731 | ```
732 |
733 | 2. **Wrapping in Operators**: Similar to using parentheses for invocation, the `!`, `+`, or `-` operators are sometimes used for invoking clarity. For instance:
734 | ```javascript
735 | !function(){
736 | console.log('Invoked!');
737 | }();
738 | ```
739 |
740 | 3. **Named IIFE**: Though not as common, naming an IIFE can assist with self-referencing. This is most effective when the intention is to have a more comprehensive stack trace during debugging.
741 | ```javascript
742 | (function factorial(n){
743 | if (n <= 1) return 1;
744 | return n * factorial(n-1);
745 | })(5);
746 | ```
747 |
748 | #### Caution on Minification
749 |
750 | When leveraging IIFEs, exercise caution while using minifiers to shrink JavaScript files. Minification might lead to unintended outcomes, altering the previous scope expectations.
751 |
752 |
753 | ## 15. How do you create _private variables_ in JavaScript?
754 |
755 | In JavaScript, encapsulating private state within an object can be achieved using a **closure**. This ensures the state is local to the object and not directly accessible from outside.
756 |
757 | ### How Closures Work
758 |
759 | A **closure** allows a function to retain access to the **lexical environment** (the set of variable bindings at the point of function declaration) in which it was defined, even when the function is executed outside that lexical environment.
760 |
761 | This means that any **inner function**, defined inside another function, has access to the **outer function's variables**, and that access is maintained even after the outer function has finished executing.
762 |
763 | For example:
764 | ```javascript
765 | function outerFunction() {
766 | let outerVar = 'I am outer'; // This variable is in the lexical environment of outerFunction
767 |
768 | function innerFunction() {
769 | console.log(outerVar); // Accesses outerVar from the lexical environment of outerFunction
770 | }
771 |
772 | return innerFunction;
773 | }
774 |
775 | let myInnerFunction = outerFunction();
776 | myInnerFunction(); // Logs: "I am outer"
777 | ```
778 |
779 | Here, `innerFunction` retains access to `outerVar`.
780 |
781 | ### Practical Implementation with Constructor Functions and Modules
782 |
783 | #### Constructor Functions
784 |
785 | When defining a JavaScript **constructor function** with `function` and `new`, closure can be used to associate private state with each instance:
786 |
787 | ```javascript
788 | function Gadget() {
789 | let secret = 'top secret';
790 | this.setSecret = function (value) {
791 | secret = value;
792 | };
793 | this.getSecret = function () {
794 | return secret;
795 | };
796 | }
797 |
798 | let phone = new Gadget();
799 | phone.setSecret('new secret');
800 | console.log(phone.getSecret()); // 'new secret'
801 | ```
802 |
803 | In this example, `secret` is private to each `Gadget` instance, thanks to closure.
804 |
805 | #### Modules
806 |
807 | In modern JavaScript, **module patterns** combined with **immediately-invoked function expressions** (IIFE) are often used for encapsulation and data hiding.
808 |
809 | - The **revealing module pattern** enables selective exposure of private members.
810 |
811 | - The **IIFE pattern** immediately executes and returns the object to be assigned, effectively creating a module.
812 |
813 | Here is the code:
814 |
815 | ```javascript
816 | let myModule = (function () {
817 | let privateVariable = 'I am private';
818 |
819 | function privateMethod() {
820 | console.log('I am a private method');
821 | }
822 |
823 | return {
824 | publicMethod: function () {
825 | console.log('I am a public method');
826 | },
827 | getPrivateVariable: function () {
828 | return privateVariable;
829 | }
830 | };
831 | })();
832 |
833 | console.log(myModule.getPrivateVariable()); // 'I am private'
834 | myModule.privateMethod(); // Throws an error because privateMethod is not exposed
835 | ```
836 |
837 | In this example, `privateVariable` and `privateMethod` are accessible only within the IIFE's lexical environment, thus making them private.
838 |
839 | JavaScript tools like TypeScript and Babel also offer modules such as `module.export`, providing additional options for encapsulation.
840 |
841 |
842 |
843 |
844 | #### Explore all 100 answers here 👉 [Devinterview.io - JavaScript](https://devinterview.io/questions/web-and-mobile-development/javascript-interview-questions)
845 |
846 |
847 |
848 |
849 |
850 |
851 |
852 |
853 |
--------------------------------------------------------------------------------