DEV Community

Cover image for 5 JavaScript Questions and Answers to Test Your Skills
Juan Cruz Martinez
Juan Cruz Martinez

Posted on • Originally published at livecodestream.dev on

5 JavaScript Questions and Answers to Test Your Skills

Today we are going to continue learning our beloved JavaScript language, in this edition, we are going to test our skills by answering some JavaScript mini-challenges.

Even though I'll be giving the answer with an explanation at the end of each question, try to figure it out by yourself first, and then validate your answer against mine.

Question #1: Array Sort Comparison

Consider the following arrays and conditions, what do you think would be the result?

const arr1 = ['a', 'b', 'c']
const arr2 = ['c', 'b', 'a']

console.log(
    arr1.sort() === arr1,
    arr2 === arr2.sort(),
    arr1.sort() === arr2.sort()
)
Enter fullscreen mode Exit fullscreen mode

Answer

true true false
Enter fullscreen mode Exit fullscreen mode

Now that we know the result, let's explain why. For the first 2 outputs the explanation is rather simple, the sort() method sorts the original array and returns a reference to the same object, so arr1.sort() is actually a reference to the same object as arr1.

For the third output, arr1.sort() === arr2.sort(), even though the elements on each one of the arrays are the same, the === operator will not test the elements of the array but the reference of each object, which in this case is different, and thus returning false.

If you want to know more about array comparisons, check my article Stranger Things, JavaScript Edition, and read Scenario #5: Array equality where I explain with more samples some weird array comparisons with explanations.


Question #2: Object Mutability

For this scenario, I'd like to simulate an object which represents an author, and information about his website. We will then use the method Object.freeze() so it can't be changed, and we will put it to the test. What do you think will be the result?

const author = {
  name: 'Juan',
  website: {
    type: 'blog',
    url: 'https://livecodestream.dev',
  }
}

Object.freeze(author)

author.website.type = 'test'

console.log(author.website.type)
Enter fullscreen mode Exit fullscreen mode

Answer

test
Enter fullscreen mode Exit fullscreen mode

If you got it right congrats! if not, don't worry, I was there too. Let's explain what happened.

When we called the method Object.freeze() we froze the object, meaning that the object cannot longer be changed; freezing an object prevents new properties from being added to it, existing properties from being removed or changed.

But then why were we able to change the object? Actually we didn't, and that's the trick. For all purposes in the variable author website is a reference to an object, and that reference remains the same throughout the code. We did change one attribute inside the website object, but that doesn't change the reference to the object itself.

If you are wondering what would happen if we try to change a direct property of the author object, there are 2 possible answers. Let's start with the first:

author.name = 'Laura'
console.log(author.name)

---------
Output
---------
"Juan"
Enter fullscreen mode Exit fullscreen mode

In this first scenario, even though we change the property name nothing really changed, we got no error, no warning, is like that line of code would have never been executed. The second option is in strict mode

"use strict"; author.name = 'Laura'
Uncaught TypeError: Cannot assign to read only property 'name' of object '#<Object>'
    at <anonymous>:1:27
Enter fullscreen mode Exit fullscreen mode

In strict mode, if we try to modify a frozen object we get a TypeError. Much better than before.


Question #3: Recursion

Given the following recursive function, what do you think the result would be when we call it with "blog" as a parameter?

const recursive = str => {
  if (str.length > 1) {
      return recursive(str.slice(1))
  }

  return str
}

console.log(recursive('blog'))
Enter fullscreen mode Exit fullscreen mode

Answer

g
Enter fullscreen mode Exit fullscreen mode

For this question there is no trick, is just a basic use of a recursive function, which will continue calling itself until there's only one element in the string str, thus printing the last character of the original string, in this case g.
Recursive functions are important and can resolve problems in very interesting ways, and it's important that we understand them.


Question #4: Scopes

What do you think the output to the console would be and why?

(function(){
  const a = b = 3
})()

console.log("a defined? " + (typeof a !== 'undefined'))
console.log("b defined? " + (typeof b !== 'undefined'))
Enter fullscreen mode Exit fullscreen mode

Answer

a defined? false
b defined? true
Enter fullscreen mode Exit fullscreen mode

Weird alert! Since both a and b are defined within the enclosing scope of the function, you would expect that both a and b are actually undefined.

However, that is not the case. The issue here is the common misunderstanding that const a = b = 3 is a shorthand for: const a = 3; const b = 3; but in fact, it's a shorthand for

b = 3;
const a = b;
Enter fullscreen mode Exit fullscreen mode

But how can b be defined outside of the scope of the enclosing function? The trick is that b ends up being a global variable (as is not preceded by let, const or var). But a remains under the enclosing of the function.

Note that, in strict mode, this will generate a ReferenceError: b is not defined.


Question #5: More on closures

The following snippet is an actual popular interview question, the question is, what do you think the output would be?

for (var i = 0; i < 5; i++) {
  setTimeout(function() { console.log(i); }, i * 1000 );
}
Enter fullscreen mode Exit fullscreen mode

Answer

5
5
5
5
5
Enter fullscreen mode Exit fullscreen mode

Not exactly what you expected? The reason for this is that each function executed within the loop will be executed after the entire loop has completed and all will, therefore, reference the last value stored in i, which was 5.

Closures can be used to prevent this problem by creating a unique scope for each iteration, storing each unique value of the variable within its scope, as follows:

for (var i = 0; i < 5; i++) {
    (function(x) {
        setTimeout(function() { console.log(x); }, x * 1000 );
    })(i);
}
Enter fullscreen mode Exit fullscreen mode

Another option available from ES2015 is to use let instead of var:

for (let i = 0; i < 5; i++) {
    setTimeout(function() { console.log(i); }, i * 1000 );
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

I hope you had fun and learn with it as much as I did, it has been a particularly fun article to write, and I may do more like this in the future.

Please let me know in the comments if you have some other questions you want to have answered, or simply if you enjoyed the article or not.

Thanks so much for reading!


If you like the story, please don't forget to subscribe to our newsletter so we can stay connected: https://livecodestream.dev/subscribe

Top comments (0)