As part of my journey to become a better JavaScript programmer, I need to dive deep into JavaScript foundations. In this article, I'll show you mind-boggling questions (for me, it was mind-boggling, I hope for you as well) that we can learn some of the concepts behind these questions.
Before we start, I want to mention some of the resources I used for writing this article, and I highly recommend you to use them as well:
- 70 JavaScript Interview Questions - Excellent article that you can learn a lot about JavaScript foundations.
- What Makes Javascript Weird...and AWESOME - I found this Youtube playlist, In my opinion, the explanations are very understandable, and he shows visual code examples.
- What the heck is the event loop anyway? | Philip Roberts | JSConf EU - One of the most famous JavaScript videos recently. He explains how JavaScript works "Behind the scenes" (how the event loop works).
Of course, this is only some of the resources on the subject. There are many other resources to learn from.
So are you ready to get your mind blow away (from JavaScript question)?
Questions
Notice 1!: To each question, there is an answer with an explanation (link below each item).
Notice 2!: If you run the questions on the console, remember that some of the variables are repeating themselves, so do refresh from question to question.
Notice 3!: For each question think what will be the output.
Question 1
var a = 1
function foo(){
var a = 2
console.log(a)
}
foo()
console.log(a);
Go to answer 1
Question 2
function foo(){
a = 2
}
foo()
console.log(a);
Go to answer 2
Question 3
var answer = 0;
const baseValue = value => multipleValue => value * multipleValue;
const multiple = baseValue(2);
answer = multiple(5);
console.log(answer);
Go to answer 3
Question 4
function outerFunc(outerParam) {
function innerFunc(innerParam) {
outerParam["b"] = innerParam;
}
return innerFunc;
}
const obj = {a:1}
const example = outerFunc(obj);
const answer = example(2)
console.log(obj);
Go to answer 4
Question 5
let arr =[1,2]
function test(array){
array.push(3)
}
test(arr)
console.log(arr)
Go to answer 5
Question 6
let arr =[1,2]
function test(array){
array.push(3)
}
test([...arr])
console.log(arr)
Go to answer 6
Question 7
let arr =[1,2]
function test(array){
array = [1,2,3]
}
test(arr)
console.log(arr)
Go to answer 7
Question 8
const carDetails = {
name: "Tomer",
getName(){
return this.name;
},
};
var name = "Joe";
var getCarName = carDetails.getName;
console.log(getCarName());
Go to answer 8
Question 9
console.log(a)
console.log(b)
var a = 2
let b = 2
Go to answer 9
Question 10
a()
function a(){
console.log("a")
}
b();
var b =function(){
console.log("b")
}
Go to answer 10
Answers
Answer To Question 1
I think the answer is pretty straightforward. If you said 2
and 1
, you are correct. This question is about Scope. In JavaScript, there are two types of scopes: Global Scope and Local Scope, variables declared within a JavaScript function become local, and variables declared outside of the function become global.
The var a = 1
declared out of the function and saved in global memory. The var a = 2
declared inside the function and saved in local memory. it's a different place in memory (even if they have the same name).
Answer To Question 2
If you said a is not defined,
you have healthy thinking, but the answer is 2
. This is why JavaScript is a unique language. According to the logic we talked about in the previous question, the variables should be in local scope, But, if you pay attention, the variables didn't declare (without var
, let
, const
). When we do assignments without declarations in JavaSacript (a=2
), the compiler will save the variable in the global scope. FYI, we can fix this behavior by add "use strict"
.
Answer To Question 3
The answer is 10
. This question is about Closures. In simple words - Closures are functions that return another function, and the inner function has access to the outer variables function (You can read more here). We can look at Closures like Global scope (outer function) and Local scope (inner function) that leaves inside the local scope (baseValue
). Like regular Scope in JavaScript, the Local scope has access to Global Scope. For that reason, the compiler can know what is value
.
FYI, This doesn't seem like a "conservative" Closure example because it's writing in ES5 syntax (arrow function). The "conservative" looks like:
var answer = 0;
function baseValue(value){
return function(multipleValue){
return value * multipleValue;
}
}
const multiple = baseValue(2);
answer = multiple(5);
console.log(answer);
Answer To Question 4
The answer is {a: 1,b: 2}
. After the previous question, we can recognize it's a Closure, but this question is also about References. In JavaScript, there are two kinds of variables types: primitives variables (strings, numbers, and booleans) and References variables (arrays and objects). Primitives variables save in memory in their values, and references save in memory as virtual id. For that reason, when we pass the object from function to function, we actually pass the virtual id. In our case, the compiler saved the obj
and saw we call the reference again by outerParam["b"] = innerParam.
Hence, he added to the object key b
and value 2
(value of innerParam).
In the case of primitives variables like:
function outerFunc(outerParam) {
function innerFunc(innerParam) {
outerParam = innerParam;
}
return innerFunc;
}
const num = 1
const example = outerFunc(num);
const answer = example(2)
console.log(num);
The num
will still be 1
(but the outerParam will be 2).
Answer To Question 5
The answer is [1,2,3]
, arrays are References (full explanation in the previous answer).
Answer To Question 6
The answer is [1,2]
. I used the ES6 "Spread Operator," it's basically the same do test([1,2,3])
. In this way, we created a new array (new reference) and arr
reference saved in different id - we didn't change the reference just added another one.
Answer To Question 7
The answer is [1,2]
. I know that after all the explanations on references, it seems weird. Still, there is a good reason for it, The =
Operator creates a new reference (you can look in this discussion for more information), The array
exist in the local scope and don't influence the global variables in this case.
If the code was like:
let arr =[1,2]
function test(array){
arr = [1,2,3]
}
test(arr)
console.log(arr)
The answer was [1,2,3]
because, in this case, we replaced the global variable (arr
) with a new reference.
Answer To Question 8
The answer is Joe
. The question's subject is "Context"(this
). In JavaScript, this
is the object that is called to the function. When we do var getCarName = carDetails.getName;
we store the function in the global scope, So this will be Window,
and because we set name
in the global scope (window), the output will be Joe
(same as window.name). This is JavaScript's default behavior. If you want to change this behavior, you can use: bind, apply, call, and arrow functions.
Answer To Question 9
If you said undefined
and b is not defined
(error), congratulation, you know Hoisting. In simple words, hoisting is the way the compiler defines the variables. When the function executes, the compiler looks for variables declaration, and if the variable were declared, it would hoist it to the top. it's the same as:
var a;
console.log(a)
a = 2
It only works on var
. let
and const
is not "hoisting" variables. This is why we will see the error: b is not defined.
Answer To Question 10
The answer is a
and b is not a function
(error). This is a very wried part of JavaScript (in my point of view) - functions are hoisted as well. If you read the last answer, you will understand that var
is also hoisted, but it doesn't matter what will be after the =
operator. In the hoisting stage, he will always be undefined
. So when we do b()
, it's the same as undefined().
Thank you for reading this article. I hope you enjoyed and learned new things. If you have any questions or suggestions, please leave a comment.
Top comments (20)
Nice round up. Great to refresh some tricky aspects.
In Q9, I’d like to clarify that let and const are also hoisted but can’t be accessed before declaration due to what is called Temporal Dead Zone.
Ref: jsrocks.org/2015/01/temporal-dead-...
very interesting read, thanks!
Thanks :)
Thank you for the response, I didn't know it, I thought
const
andlet
are not hoisted, but your explanation makes more sense.Thanks for Sharing. Also learn top JavaScript Tricky Interview questions
At first, thanks for all the examples and explanations! When I was taking this quiz, a thought "who ever write code this way?" appeared too many times :) I think these questions are good as a tricksters for A-graders, but if this kind of code somehow had appeared in PR, I would have never approved it
Thank you for the feedback, but can you elaborate more on your response? These questions were made for developers to strengthen their knowledge (even if you know the answer). The examples were made to be very simple, only to understanding the concept behind the question.
Well, my message wasn't about all the questions, most of them cover underlying concept and doesn't contradict to real world. But examples about hoisting or array reference looks like smelly code. Though I didn't check with my IDE and SonarLint that examples, I'm almost sure I'll get warnings.
P.S. english is not my native lang, so I'm bot sure 'bout the tone of voice of my message, hope it's not seems offensive or smth
On the contrary, I glad to hear feedback, even if it negative. I will take your tips to my attention. Thanks
Hi, on number 3 I do not think definition of clousure is correct. Because a closure is not a function that return another function. As per your example is the variable value that gets a reference to param 2. So the variable get close inside the scope and by that the function cant return. In your example the closure refers to value.
I'm not sure you are correct, And I didn't understand completely what you mean. But, I think we say the same thing. I believe it doesn't matter if you know the exact definition of closure "by the book", the most important thing it's to understand the concept.
10x mate :-) , it's always important to refresh the basics.
In Q8 - Running the code in Node will result undefined , see more details :
stackoverflow.com/questions/602986...
Thank you for the response. It's is very helpful. You right, The window object exists only in the browser (client-side). I wanted to show the basic concepts of javascript. The scope of node js it's a little bit different. You can create a
global
variable by doingglobal.length
(not recommended) - but without it, I thinkthis
won't know whatlength
is. if you that in node.js it will work:Thank you so much for this quiz. I have scored 7/10 and last two questions help me to understand hoisting in more clear way. 🤯
Very useful questions that help me revise my JavaScript knowledge. Thank you!
Very happy to hear. Thank you for the comment
Answer to nr 5 is wrong though. It is [1,2,3] because in the function argument you pass the same referrence that you are logging.
Aa dude, my bad, the answer is actually corect, but the anchor takes me to the answer to Q6 and I didn’t realise.
Nice brother. I was also confused when you said hoisting only works for var and then asked to ChatGPT and see comments, which helped me to understand. You should update that hosting part.
Thank you! I glad it helped you. And thank you for sharing the video.