JavaScript Interview Questions for Beginners: Code Examples on variable scoping.” — PART 1
What is JavaScript?
JavaScript is a high-level scripting language(just-in-time compiled language) primarily used in web development. It runs in web browsers, allowing developers to enhance user interfaces through dynamic content, event handling, and asynchronous operations. JavaScript supports multiple data types, functions, and object-oriented programming concepts. It’s crucial for client-side interactions and has a robust ecosystem of libraries and frameworks.
JavaScript Code Snippets with Explanations:
(function(){
setTimeout(() => console.log(1), 2000);
console.log(2);
setTimeout(() => console.log(3), 0);
console.log(4);
})();
Explanation and Highlighted JavaScript Features:
- Self-Invoking Function: The code begins with an immediately-invoked function expression (IIFE) wrapped in parentheses
(function(){ ... })()
. This structure allows for encapsulation and prevents variable pollution in the global scope. - Asynchronous Operations with
setTimeout
:setTimeout(() => console.log(1), 2000);
: This line schedules a callback function to execute after a delay of 2000 milliseconds (2 seconds). It demonstrates asynchronous behavior, as it doesn't block the rest of the code execution. setTimeout(() => console.log(3), 0);
: Here, a callback function is scheduled with a delay of 0 milliseconds. This is interesting because even with a delay of 0, it's not guaranteed to execute immediately due to JavaScript's event loop mechanism.- Order of Execution:
console.log(2);
andconsole.log(4);
are synchronous operations, so they execute immediately when encountered in the code. console.log(2)
andconsole.log(4)
output values2
and4
respectively, and they are logged before the asynchronous operations.- The order of execution may seem intuitive at first, but the asynchronicity introduced by
setTimeout
results in a different order of logging.
Order of Console Output:
2
is logged immediately because it's a synchronous operation.4
is also logged immediately for the same reason.3
is logged before1
, even though it has a shorter timeout, because it's scheduled in a different "task" within the event loop.- Finally, after a delay of 2 seconds,
1
is logged.
This code illustrates key JavaScript features like asynchronous programming using setTimeout
, the event loop, and the order of execution in a non-blocking environment. It's a valuable example for understanding how JavaScript handles concurrency and timing in web applications.
function dummy() {
for (var i = 0; i < 3; i++) {
console.log(i);
}
console.log(i);
}
dummy()
Explanation and Highlighted JavaScript Features:
- The code defines a JavaScript function named
dummy
. Functions in JavaScript are reusable blocks of code - For Loop: Inside the
dummy
function, there is afor
loop. This loop is used to execute a block of code repeatedly. - Variable Scope: The loop variable
i
is declared usingvar
, which means it has function-level scope. This implies thati
is accessible both inside and outside the loop within thedummy
function.
0
1
2
3
- The loop runs while
i
is less than3
, so it logs0
,1
, and2
. - After the loop exits, the line
console.log(i);
outside the loop attempts to log the value ofi
. Sincei
was declared withvar
, it still exists in the function's scope, and its value remains3
from the last iteration.
This code example demonstrates the use of a for
loop, variable scope, and how variables can be accessed within and outside the loop. It's a fundamental concept in JavaScript and programming in general.
function dummy() {
for (let i = 0; i < 3; i++) {
console.log(i);
}
console.log(i);
}
Output
0
1
2
Uncaught ReferenceError: i is not defined
Explanation:
- The loop operates as expected, logging
0
,1
, and2
during its three iterations. - After the loop exits, the line
console.log(i);
attempts to log the value ofi
. However, this time it results in aReferenceError
. This is becausei
is block-scoped due to the use oflet
, and it's not accessible outside of the loop's block.
Key Takeaway
The use of let
in this code introduces block-level scope for the loop variable i
, preventing it from being accessed outside of the loop. This is a significant difference from the previous code snippet, where var
provided function-level scope. Understanding variable scope is crucial in JavaScript, especially when dealing with loops and block-level variables.
function dummy() {
for (var i = 0; i < 3; i++) {
setTimeout(function() {
console.log(i);
});
}
console.log(i);
}
Loop Execution:
The for
loop runs three times, incrementing i
from 0
to 2
. However, the critical aspect to note is that the setTimeout
function schedules the execution of the anonymous function, but it doesn't execute it immediately. Instead, it continues to the next iteration of the loop.
Console Output:
When the dummy
function is called, it will produce the following output:
3
3
3
Explanation:
- The loop runs three times, incrementing
i
each time. - The
setTimeout
function is called three times within the loop, each time scheduling the anonymous function for execution. - After the loop exits, the line
console.log(i);
is executed. Sincei
is declared withvar
, it has function-level scope and retains its final value of3
from the last iteration of the loop. As a result,3
is logged three times.
Key Takeaway:
The behaviour of setTimeout
combined with the function-level scope of var
can lead to unexpected results. In this example, all three scheduled console.log
statements inside the setTimeout
functions print 3
, as they reference the same variable i
. Understanding closures and scoping in JavaScript is essential to work with asynchronous code effectively.
function dummy(){
for(let i=0;i<3;i++){
setTimeout(function()=>{
console.log(i);
})
}
console.log(i);
}
Loop Execution:
The for
loop runs three times, incrementing i
from 0
to 2
. Each iteration schedules a setTimeout
function with an anonymous arrow function.
Console Output:
When the dummy
function is called, it will produce the following output:
0
1
2
3
Explanation:
- The loop runs three times, and during each iteration, it schedules a
setTimeout
function that logs the value ofi
. Sincei
is block-scoped bylet
, each anonymous arrow function "captures" the value ofi
at the time it was created. - After scheduling the
setTimeout
functions, the loop exits, and the lineconsole.log(i);
is executed.i
is still accessible here, and it has the value3
because that was the value ofi
after the loop finished.
Key Takeaway:
The use of let
in this code ensures that each anonymous arrow function created inside the loop captures the correct value of i
at the time it was defined. This behaviour is different from the var
example and demonstrates block-level scoping in JavaScript, which can help avoid common issues when working with asynchronous code.
function sayHi() {
console.log(name);
console.log(age);
var name = 'Nick';
let age = 21;
}
sayHi();
Console Output
undefined
21
Explanation:
- The
console.log(name);
statement logsundefined
forname
because the variablename
is declared usingvar
. Variables declared withvar
are hoisted, which means they are moved to the top of their containing function or block during the compilation phase. However, only the declaration is hoisted, not the initialisation. So,name
is declared but not yet assigned a value whenconsole.log(name);
is executed. - The
console.log(age);
statement logs21
forage
becauselet
declarations are also hoisted but are not initialised until the point in the code where they are declared. In this case,age
is declared and initialised with the value21
in the same statement, so it is accessible and holds the correct value whenconsole.log(age);
is executed.
Key Takeaway:
This code illustrates the difference in behaviour between variables declared with var
and those declared with let
in terms of hoisting and initialisation. Understanding these differences is crucial for writing predictable JavaScript code.
(function() {
var a = b = 5;
})();
console.log(b);
Immediately-Invoked Function Expression (IIFE): The code starts with an immediately-invoked function expression (IIFE) wrapped in parentheses (function() { ... })();
. IIFE is a way to create a function and execute it immediately.
Variable Scope and Assignment:
When var a = b = 5;
is executed, the following happens:
var a
is correctly declared and assigned the value5
within the function's scope.b = 5
assigns the value5
to a variableb
. However, becauseb
is declared withoutvar
orlet
, it becomes an implicit global variable (i.e., it becomes a property of the global object, usuallywindow
in the browser).
Output:
5
Explanation:
- The
console.log(b);
statement logs5
becauseb
has become a global variable due to the absence ofvar
orlet
in its declaration within the IIFE. - The value
5
assigned tob
within the IIFE is accessible in the global scope, so it can be logged outside of the IIFE.
Important Note:
While this code works as described, it’s generally considered good practice to explicitly declare variables using var
, let
, or const
to avoid unintentional global variable creation. In this case, using var a = 5; var b = 5;
within the IIFE would have prevented b
from becoming a global variable.
(function() {
'use strict';
var a = window.b = 5;
})();
console.log(b);
Strict Mode: The string 'use strict';
is placed at the beginning of the IIFE. This activates strict mode for the code within the IIFE. Strict mode is a set of rules that make JavaScript less error-prone and more secure.
Variable Scope and Assignment:
When var a = window.b = 5;
is executed:
var a
is correctly declared within the function's scope and assigned the value5
.window.b = 5
assigns the value5
to a variableb
. However, this time it explicitly setsb
as a property of thewindow
object. This makesb
a global variable accessible aswindow.b
.
Output
5
Explanation:
- The
console.log(b);
statement logs5
becauseb
was explicitly assigned as a global variable attached to thewindow
object within the IIFE. - Due to strict mode, the code behaves as intended without creating any unintentional global variables.
Important Note:
While explicitly attaching properties to the window
object is possible, it's generally not recommended as it can lead to global variable pollution and make code harder to maintain. Using strict mode helps catch such unintentional global variable assignments and promotes better coding practices.
function test() {
console.log(a);
console.log(foo());
var a = 1;
function foo() {
return 2;
}
}
test();
var a = 1;
: This line declares a variablea
using thevar
keyword and assigns it the value1
. Variables declared withvar
are function-scoped.function foo() { return 2; }
: This line declares a function namedfoo
using thefunction
keyword. Function declarations are also hoisted, so the function is available for use within the entire function scope.
Code Execution:
Now, let’s see how the code executes:
console.log(a);
: This line attempts to log the value ofa
to the console before it has been assigned a value. Sincevar
declarations are hoisted,a
is declared but not yet initialised at this point. So,a
isundefined
.console.log(foo());
: This line calls thefoo
function and attempts to log its return value. Thefoo
function returns2
, so2
is logged to the console.
undefined
2
Explanation:
- The first
console.log(a);
statement logsundefined
becausea
is declared withvar
and is hoisted but not yet initialized. - The second
console.log(foo());
statement logs2
because thefoo
function is called, and it returns2
.
Key Takeaway:
This code demonstrates variable hoisting and function declarations within a JavaScript function. Understanding hoisting and variable/function scope is essential when working with JavaScript to avoid unexpected behaviour.
Conclusion:
In this comprehensive guide to JavaScript interview questions, we’ve explored a variety of code examples and concepts that can help you prepare for your upcoming interviews. Let’s recap the key takeaways:
- Understanding Scopes: JavaScript has function-level and block-level scopes. Variables declared with
var
have function-level scope, whilelet
andconst
introduce block-level scope. Be aware of how variable scope affects your code. - Hoisting: JavaScript hoists variable and function declarations to the top of their containing scope. This behavior can lead to surprises if you’re not careful, so it’s crucial to understand how it works.
- Global Variables: Avoid unintentional global variable creation. Always declare your variables with
var
,let
, orconst
to control their scope and prevent pollution of the global namespace. - IIFE: Immediately-Invoked Function Expressions (IIFE) are a powerful tool for creating isolated scopes in JavaScript. They can help prevent global variable conflicts and maintain code clarity.
- Strict Mode: Enable strict mode in your scripts using
'use strict';
. It enforces better coding practices, catches common mistakes, and makes your code more predictable. - Practice Makes Perfect: Regular practice is essential for improving your coding skills. Work on coding challenges, study different JavaScript concepts, and write clean, efficient code.
- Seek Feedback: Don’t hesitate to seek feedback from peers, mentors, or online coding communities. Constructive feedback can help you identify areas for improvement.
- Stay Confident: Confidence is key in interviews. Stay calm, articulate your thought process, and don’t be afraid to ask clarifying questions if you’re unsure about a problem.
By reviewing and practicing the code examples provided in this guide, you’ll not only gain a deeper understanding of JavaScript but also build the skills and confidence needed to excel in your next technical interview. Remember, interview success comes with practice and continuous learning. Best of luck on your coding journey!