The following questions are intended to be challenging and instructive. If you know exactly how to answer each one, that's great, but if you get some wrong and learn why you got it wrong, I contend that's even better!
Let me know in the comments if you learn anything from the quiz!
If you enjoy this quiz, please give it a 💓, 🦄, or 🔖 and consider:
- signing up for my free weekly dev newsletter
- subscribing to my free YouTube dev channel
Question 1: IIFE, HOF, or Both
Does the following snippet illustrate an Immediately-Invoked Function Expression (IIFE), a Higher-Order Function (HOF), both, or neither?
((fn, val) => {
return fn(val);
})(console.log, 5);
Answer and Explanation
Answer: Both IIFE and HOF
The snippet clearly illustrates an IIFE as we immediately invoke a function by passing console.log
and 5
to it. Additionally, we find that this is a HOF as fn
is a function, and a HOF is defined as any function that takes another function as a parameter or returns a function.
Question 2: Array-to-Object Efficiency
Both a
and b
are objects with the same properties and values. Which is created more efficiently?
const arr = [1, 2, 3];
const a = arr.reduce(
(acc, el, i) => ({ ...acc, [el]: i }),
{}
);
const b = {};
for (let i = 0; i < arr.length; i++) {
b[arr[i]] = i;
}
Answer and Explanation
Answer: b
When b
is being set, the b[arr[i]]
property is set to the current index on each iteration. When a is being set, the spread syntax (...
) will create a shallow copy of the accumulator object (acc
) on each iteration and additionally set the new property. This shallow copy is more expensive than not performing a shallow copy; a
requires the construction of 2 intermediate objects before the result is achieved, whereas b
does not construct any intermediate objects. Therefore, b
is being set more efficiently.
Question 3: Batman v. Superman
Consider the following superheroMaker
function. What gets logged when we pass the following two inputs?
const superheroMaker = a => {
return a instanceof Function ? a() : a;
};
console.log(superheroMaker(() => 'Batman'));
console.log(superheroMaker('Superman'));
Answer and Explanation
Answer: "Batman" "Superman"
When passing () => 'Batman'
to superheroMaker
, a
is an instance of Function
. Therefore, the function gets called, returning the string "Batman"
. When passing "Superman"
to superheroMaker, a
is not an instance of Function
and therefore the string "Superman"
is just returned. Therefore, the output is both "Batman"
and "Superman"
.
If you enjoy this quiz, please give it a 💓, 🦄, or 🔖 and consider:
- signing up for my free weekly dev newsletter
- subscribing to my free YouTube dev channel
Question 4: Object Keys, Object Values
Consider the following object.
const obj = {
1: 1,
2: 2,
3: 3
};
Is Object.keys
equal to Object.values
?
console.log(Object.keys(obj) == Object.values(obj));
Answer and Explanation
Answer: false
In this case, Object.keys
converts the keys to be string ["1", "2", "3"]
and Object.values
gives [1, 2, 3]
. Even if the values turn out to be the same type, the two arrays are both different objects in memory, so the equality comparison will return false
. You will see a lot of quiz questions here drilling into the concepts of object and array comparison!
Question 5: Basic Recursion
Consider the following recursive function. If we pass the string "Hello World"
to it, what gets logged?
const myFunc = str => {
if (str.length > 1) {
return myFunc(str.slice(1));
}
return str;
};
console.log(myFunc('Hello world'));
Answer and Explanation
Answer: "d"
The first time we call the function, str.length
is greater than 1 ("Hello World"
is 11 characters), so we return the same function called on str.slice(1)
, which is the string "ello World"
. We repeat this process until the string is only one character long: the character "d"
, which gets returned to the initial call of myFunc
. We then log that character.
Question 6: Function Equality
What gets logged when we test the following equality scenarios?
const a = c => c;
const b = c => c;
console.log(a == b);
console.log(a(7) === b(7));
Answer and Explanation
Answer: false true
In the first test, a
and b
are different objects in memory; it doesn't matter that the parameters and return values in each function definition are identical. Therefore, a
is not equal to b
. In the second test, a(7)
returns the number 7
and b(7)
returns the number 7
. These primitive types are strictly equal to each other.
In this case, the equality (==
) vs identity (===
) comparison operators don't matter; no type coercion will affect the result.
Question 7: Object Property Equality
a
and b
are different objects with the same firstName
property. Are these properties strictly equal to each other?
const a = {
firstName: 'Bill'
};
const b = {
firstName: 'Bill'
};
console.log(a.firstName === b.firstName);
Answer and Explanation
Answer: true
The answer is yes, they are. a.firstName
is the string value "Bill"
and b.firstName
is the string value "Bill"
. Two identical strings are always equal.
Question 8: Function Function Syntax
Let's say myFunc
is a function, val1
is a variable, and val2
is a variable. Is the following syntax allowed in JavaScript?
myFunc(val1)(val2);
Answer and Explanation
Answer: yes
This is a common pattern for a higher-order function. If myFunc(val1)
returns a function, then that function will be called with val2
as an argument. Here's an example of this in action that you can try out:
const timesTable = num1 => {
return num2 => {
return num1 * num2;
};
};
console.log(timesTable(4)(5));
// 20
Question 9: Object Property Mutation
Consider objects a
and b
below. What gets logged?
const a = { firstName: 'Joe' };
const b = a;
b.firstName = 'Pete';
console.log(a);
Answer and Explanation
Answer: { firstName: 'Pete' }
When we set b = a
in the second line, b
and a
are pointing to the same object in memory. Changing the firstName
property on b
will therefore change the firstName
property on the only object in memory, so a.firstName
will reflect this change.
Question 10: Greatest Number in an Array
Will the following function always return the greatest number in an array?
function greatestNumberInArray(arr) {
let greatest = 0;
for (let i = 0; i < arr.length; i++) {
if (greatest < arr[i]) {
greatest = arr[i];
}
}
return greatest;
}
Answer and Explanation
Answer: no
This function will work fine for arrays where at least one value is 0
or greater; however, it will fail if all numbers are below 0
. This is because the greatest variable starts at 0
even if 0
is greater than all array elements.
If you enjoy this quiz, please give it a 💓, 🦄, or 🔖 and consider:
- signing up for my free weekly dev newsletter
- subscribing to my free YouTube dev channel
Want more quiz questions? Head over to https://quiz.typeofnan.dev for 72 JavaScript quiz questions!
Top comments (18)
Just noting that === is not an identity operator -- it's the strict equality comparison operator.
We can easily tell that it is not an identity operator because, e.g., NaN === NaN is false.
It's a bit problematic to say this, since Javascript doesn't have pointers.
It's sufficient to say that a and b have the same value, so they are the same object, and so provide access to the same properties. The rest then follows as you've said.
the equality operator (==) will attempt to make the data types the same before proceeding
the identity operator (===) requires both data types to be the same, as a prerequisite.
We can tell that === is not an identity operator since it may return false when comparing a value with itself.
e.g. NaN === NaN.
NaN === NaN // false,
The identity evaluation algorithm (IEA) rule 4
Operands are the same type (numbers), but the IEA rule 4 indicates than nothing is equal with a NaN.
The result is false.
Also,
NaN
s are the only non-reflexive value, i.e.,if x !== x, then x is a NaN
more details:
dmitripavlutin.com/the-legend-of-j...
The page you've referenced is mostly correct, but they're a bit confused on terminology, and have made things rather more complicated that necessary.
See: ecma-international.org/publication...
Now, what this means is that some things with the same identity compare false with ===, and some things with different identities compare true with ===.
e.g.
NaN === NaN is false
-0 === 0 is true
Which means that it is not checking the identity of the operands -- it is computing a kind of equality (using the strict equality comparison).
So, === is not an identity operator, and for these reasons is not called an identity operator in the language specification.
It's just some confused people on the internet who are making that into a popular mistake. :)
Some instructive feedback for question 10: initialize greatest to
-Infinity
(orarr[0]
)These are very nice questions that probe JavaScript fundamentals and not ephemeral trivia. I suggest you change #4 and #6 so that they don't require knowledge about the behavior of == vs. ===. (Nobody should use == with JavaScript in 2020.) If you think that makes #4 too easy, perhaps you could add whether
Object.keys(obj).map(x => parseInt(x)) === Object.values(obj)
. And as a bonus puzzler, why isn'tObject.keys(obj).map(parseInt)
the same asObject.keys(obj).map(x => parseInt(x))
?Love the bonus question! That's quite the trap.
Very cool I love these. I am going to try the quiz in the link =)
Nice quiz. I enjoyed it more than other JS quizzes I have seen.
In Question 2 though, since it is about performance, it might be useful to know that a
var
declaration in afor
loop is more performant than alet
declaration. As long as yourfor
loop is scoped to a function, you should not get any nasty surprises.An example could be:
Here are 156 others:
github.com/lydiahallie/javascript-...
I'm learning Javascript, I have bookmarked this post.
I would like to come here later and check how many I can answer.
Thank you for this post
Don't forget to check these articles:
dev.to/macmacky/70-javascript-inte...
github.com/lydiahallie/javascript-...
Hey Nick ! I really liked the blog and wanted to tell you that as of now(16th March 2023 22:02 IST) my Like made your existing likes sum up to 200 . Than u so much for your work . Kindly keep Sharing your knowledge with us
Nice. Learnt many things. Thanks!
Cool post Nick, I've subscribed to your newsletter to getting some quality posts 🤟