DEV Community

Tomer Raitz
Tomer Raitz

Posted on

Tricky JavaScript Questions

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:

  1. 70 JavaScript Interview Questions - Excellent article that you can learn a lot about JavaScript foundations.
  2. 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.
  3. 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)?

Alt Text

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);
Enter fullscreen mode Exit fullscreen mode

Go to answer 1

Question 2
function foo(){
    a = 2
  }
  foo()
  console.log(a);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

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);
Enter fullscreen mode Exit fullscreen mode

Go to answer 4

Question 5
let arr =[1,2]
function test(array){
  array.push(3)
}
test(arr)
console.log(arr)
Enter fullscreen mode Exit fullscreen mode

Go to answer 5

Question 6
let arr =[1,2]
function test(array){
  array.push(3)
}
test([...arr])
console.log(arr)
Enter fullscreen mode Exit fullscreen mode

Go to answer 6

Question 7
let arr =[1,2]
function test(array){
  array = [1,2,3]
}
test(arr)
console.log(arr)
Enter fullscreen mode Exit fullscreen mode

Go to answer 7

Question 8
const carDetails = {
    name: "Tomer",
    getName(){
       return this.name;
    },
  };
  var name = "Joe";
  var getCarName = carDetails.getName;
  console.log(getCarName());
Enter fullscreen mode Exit fullscreen mode

Go to answer 8

Question 9
console.log(a)
console.log(b)
var a = 2
let b = 2
Enter fullscreen mode Exit fullscreen mode

Go to answer 9

Question 10
a()
function a(){
    console.log("a")
}
b();
var b =function(){
    console.log("b")
}
Enter fullscreen mode Exit fullscreen mode

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).

Back to question 1

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".

Back to question 2

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);
Enter fullscreen mode Exit fullscreen mode

Back to question 3

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);
Enter fullscreen mode Exit fullscreen mode

The num will still be 1 (but the outerParam will be 2).

Back to question 4

Answer To Question 5

The answer is [1,2,3], arrays are References (full explanation in the previous answer).

Back to question 5

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.

Back to question 6

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)
Enter fullscreen mode Exit fullscreen mode

The answer was [1,2,3] because, in this case, we replaced the global variable (arr) with a new reference.

Back to question 7

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.

Back to question 8

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
Enter fullscreen mode Exit fullscreen mode

It only works on var. let and const is not "hoisting" variables. This is why we will see the error: b is not defined.

Back to question 9

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().

Back to question 10

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)

Collapse
 
satyam_prg profile image
Satyam Jaiswal

Thanks for Sharing. Also learn top JavaScript Tricky Interview questions

Collapse
 
alexparra profile image
Alex Parra • Edited

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-...

Collapse
 
zaunermax profile image
Maximilian Zauner

very interesting read, thanks!

Collapse
 
tomeraitz profile image
Tomer Raitz

Thanks :)

Collapse
 
tomeraitz profile image
Tomer Raitz

Thank you for the response, I didn't know it, I thought const and let are not hoisted, but your explanation makes more sense.

Collapse
 
ignore_you profile image
Alex

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

Collapse
 
tomeraitz profile image
Tomer Raitz

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.

Collapse
 
ignore_you profile image
Alex

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

Thread Thread
 
tomeraitz profile image
Tomer Raitz

On the contrary, I glad to hear feedback, even if it negative. I will take your tips to my attention. Thanks

Collapse
 
ninjasun profile image
ninjasun

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.

Collapse
 
tomeraitz profile image
Tomer Raitz

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.

Collapse
 
eladh profile image
Elad Hirsch

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...

Collapse
 
tomeraitz profile image
Tomer Raitz

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 doing global.length (not recommended) - but without it, I think this won't know what length is. if you that in node.js it will work:

global.length = 10;
function fn () {
  console.log (this.length);
}
fn();
Enter fullscreen mode Exit fullscreen mode
Collapse
 
blackr1234 profile image
blackr1234

Very useful questions that help me revise my JavaScript knowledge. Thank you!

Collapse
 
tomeraitz profile image
Tomer Raitz

Very happy to hear. Thank you for the comment

Collapse
 
starboysharma profile image
Pankaj Sharma

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. 🤯

Collapse
 
sahilatahar profile image
Sahil Atahar

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.

Collapse
 
sorinfratila profile image
sorinfratila

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.

Collapse
 
sorinfratila profile image
sorinfratila

Aa dude, my bad, the answer is actually corect, but the anchor takes me to the answer to Q6 and I didn’t realise.

Collapse
 
tomeraitz profile image
Tomer Raitz

Thank you! I glad it helped you. And thank you for sharing the video.