Some time ago we created a telegram-channel with JS quizzes & explanations. Today, we’d like to share TOP-5 JS challenges that were the hardest ones for developers. This TOP-5 is based on the percentage of failed answers to hundreds of the published quizzes.
We have already posted an article with the hardest topics based on the statistics of answers to these quizzes. To identify such topics we divided all published quizzes by topic (15 topics in total) and calculated the average percentage in each topic.
Top of JS Topics mostly failed by developers
How often do you ask yourself while coding: «What kind of magic is going on here?»
We should leave a note about the percentage of correct answers that you will see next to each task. You should not take this note as something constant and 100% reflecting reality. Firstly, new programmers answer our published quizzes every day and change statistics. All numbers presented in the article were fixed at the time of publication of the article. Secondly, some answers, of course, are accidentally guessed or clicked in the wrong place, etc. Nevertheless, having interviewed a huge number of JS developers, we can say with confidence that this statistics clearly reflects reality.
So let’s look at the TOP-5 most difficult JS challenges and analyze them. Spoiler: only 8% of responders solved the TOP-1 quiz correctly.
TOP-5. Default function parameters & function length property. 18% of correct answers.
The key point here is that the length property of a function is supposed to provide an info about the arity of a function, which is calculated as a number of her formal defined parameters.
Default parameters feature was introduced in ES2015. Before that all function parameters were considered as formal parameters and function length property was used to return all function parameters number.
With the introduction of default parameters, the behavior of the length property has changed. Since it is obvious that a parameter with a default value is optional, such a parameter is not included in the length of the function. According to common sense, all parameters following the parameter with a default value are also optional. Therefore, they are also not included in the length property of the function.
TOP-4. Object.defineProperty method and its default parameters. 14% of correct answers.
Most of the respondents answered
undefined to this quiz. Reason: not knowing how the Object.defineProperty() method works.
The method Object.defineProperty() defines a new property on an object, or modifies an existing property on an object.
Object.defineProperty(obj, prop, descriptors)
obj — the object on which to define or modify the property.
prop — the name of the property to be defined or modified.
descriptors — descriptors for the property.
Property descriptors are a set of flags that configure that property.
There are two types of descriptors: data descriptors (value, writable, enumerable, configurable) and access descriptors (get and set). In the context of this example, we are interested in data descriptors.
By default, properties added using Object.defineProperty() are not writable, not enumerable, and not configurable.
The configurable attribute specifies whether the property can be removed from the object, and whether the property descriptor can be changed in the future. If true, then the property will be available for deletion and modification of its descriptor, if false, then no. The default will be set to false.
Therefore, the correct answer to the quiz is
intspirit. An attempt to delete the property will be ignored. And if you run the code in strict mode, you will get an error:
TypeError: Cannot delete property ‘myCompany’ of #<Object>
TOP-3. Array.map & parseInt. 14% of correct answers.
A task of mindfulness. The Array.map() method accepts a callback function that takes 3 parameters. We will only be interested in the first two: value and index. The parseInt function takes 2 parameters: a string to convert to a number and a radix.
So in our case parseInt would be called with following arguments:
To understand how parseInt will work with those radixes, let’s take a look at radix parameter description at mdn:
1. If the input string, with leading whitespace and possible +/- signs removed, begins with 0x or 0X (a zero, followed by lowercase or uppercase X), radix is assumed to be 16 and the rest of the string is parsed as a hexadecimal number.
2. If the input string begins with any other value, the radix is 10 (decimal).
According to this definition, we get the following results:
parseInt(‘9’, 0)-> radix 0 equates to a call without radix. Because first argument does not start with 0x or 0X, radix will default to
parseInt(‘9’, 10)-> 9
parseInt(‘10’, 1)-> 1 — invalid radix (out of range) -> NaN
parseInt(‘11’, 2)-> 2 — valid radix, 11 in binary is 3 -> 3
TOP-2. Cloning an object using Object.create and Object.assign. 11% of correct answers.
There was a series of quizzes in our channel, dedicated to the differences in the work of Object.assign and …spread operator. For anyone interested in deep JS, we strongly recommend that you solve all of them. Under each quiz you will find a detailed description of how it all works. This is just a brief description of how the code in this example works, as it proved to be the most difficult for the respondents in the entire quiz series.
So.. let’s understand what happens in this example.
User constructor-function with the
verified property set to
true and its instance are created:
admin object is created using the
user object as a prototype. According to mdn:
The Object.create() method creates a new object, using an existing object as the prototype of the newly created object.
3. Two clones are created: one using the …spread operator, the other using Object.assign:
Do you know the difference between rest and spread operators? Both use three dots … but these two operators are not the same. The main difference between them is that the goal of the rest operator is to put the rest of some provided values into an array when the spread operator expands iterables into individual elements.
4. See if the
verified property was cloned:
admin object obviously has its
verified property set to
true because it uses the
user as its prototype. But, as you can see, none of the clones has the
verified property. This is because both the …spread operator and Object.assign ignore the prototype when cloning.
The prototypes of these objects:
To clone an object, including its prototype:
Note: __proto__ is only a mandatory feature in web browsers, not in JS engines in general.
TOP-1. String function & the instanceof operator. 8% of correct answers.
Absolute leader! The most difficult task out of more than a hundred specially selected non-trivial tasks. Only 2 correct answers — one of which was given by the channel admin hehe :)
What was so difficult?
If you look at the statistics of answers, you can see that the opinions of the respondents were divided approximately equally between the two wrong answers. At the time of publication of this article — 38% of developers decided that both expressions would return
true and 35% of developers thought that only the second statement was
true. The second half was closer.
It can be assumed that those who answered that the expression
‘Hello’ instanceof String is
false, while String(‘Hello’) instanceof String is
true, knew that the instanceof operator only works with objects and does not work with primitives, but got confused with what the String function returns.
In fact, both expressions are
- The instanceof operator only works on objects.
- String literal ‘Hello’ is primitive.
- String calls in a non-constructor context (called without using the new keyword) returns a primitive string.
Subscribe to the telegram-channel to become the “know-it-all” person in the office.
Follow us on Medium to not miss new articles.
Follow us on LinkedIn for other cool projects we do.
Share in the comments how many of these five quizzes did you solve correctly? Did knowledge or intuition help you?