In this story, I am going to explain the 14 questions that appeared in the quiz http://perfectionkills.com/javascript-quiz/ .
Do the quiz first. Then read this story.
# Questions
# Q1
(function () {
return typeof arguments;
})();
Here, an IIFE (Immediately-Invoked Function Expression) is defined. IIFE means, the function will invoke immediately.
“arguments” is an array that holds all the arguments of the function. In this case, the function returns typeof arguments. Everyone knows it, type of an array is “object”.
# Q2
var f = function g() {
return 23;
};
typeof g();
Here, a variable named f is defined. And its value is set to a function named g. We have to note one thing. g is defined but then assigned to f. So, g is undefined now.
So running g() will throw an error.
# Q3
(function (x) {
delete x;
return x;
})(1);
Here, again we encounter another IIFE. In this function, the “delete” keyword is used with the parameter x. But
delete is only effective on an object’s properties.
So, the “delete” operator stays silent here and 1 is returned as x’s value.
# Q4
var y = 1,
x = (y = typeof x);
x;
Here, y is defined and set to 1. Then x, y is set to the type of x. It is
executed from right to left. That means x is undefined in the “typeof x”
statement. So typeof undefined is “undefined” and that will be set to y.
What about x then? x’s value is also undefined.
Because,
The assignment operation evaluates to the assigned value.
# Q5 (My favorite one)
(function f(f) {
return typeof f();
})(function () {
return 1;
});
Here, another IIFE. A function f is defined. f expects a parameter named
f. To avoid confusion, I will refer to the function f as $f and the
parameter f as _f. Then in the second line, the function is returning the
typeof f().
But, What does f() mean? $f or _f ?. Variables are searched in the local scope first. If it’s not defined in the local scope, then the parent scope is searched. This search is continued until the variable is found or there is no parent scope.
So in this case, _f is available in the local scope (scope under $f). So,
_f is called.
What is _f? _f is the first parameter passed to the function $f. In this
case, it’s the function that returns 1. So, _f() is 1. typeof 1 is
"number". We all know that.
# Q6
var foo = {
bar: function () {
return this.baz;
},
baz: 1,
};
(function () {
return typeof arguments[0]();
})(foo.bar);
IIFE again. Here a variable named foo is defined and set to that object.
The object (foo) has 2 keys bar & baz. baz is 1. bar is a function that
returns baz. In this case, 1. (this points to the object foo).
Then comes the IIFE. The function returns the type of the value returned by its
(first argument) function. The first argument is foo.bar. foo.bar returns
this.baz. What does this mean here? Does it point to foo or something
else?
this keyword is a tricky one. I am not going to even try to explain it. To be
honest, I don’t understand it enough either. I just think of it as the “parent
context”. If the function is called normally, it points to globalThis. If it
is called as a method of an object, this points to the object. To learn more
about this in JavaScript, take a look at the
Reference page of this on MDN .
Here, arguments[0] is called normally. So, this points to globalThis now.
Whether it is window or global, baz is not defined. Hence, it returns
undefined. Finally, the IIFE returns "undefined".
# Q7
var foo = {
bar: function () {
return this.baz;
},
baz: 1,
};
typeof (f = foo.bar)();
This question is also like the previous one. foo is defined with the same
value as of #6.
Here, a variable named f gets defined and set to foo.bar. As I have mentioned
for #4, we know that, (f = foo.bar) evaluates to f. Now f wil be executed.
f is being called from the global context. Thus, inside f, this is
globalThis. globalThis.baz is undefined. So again, the typeof undefined is
“undefined”.
# Q8
var f = (function f() {
return "1";
},
function g() {
return 2;
})();
typeof f;
The comma operator is used here. Never heard of the comma operator?
The comma operator (,) evaluates each of its operands (from left to right) and returns the value of the last operand.
As of MDN’s statement, the comma operator evaluates each operand and returns the
rightmost value. In this case, g is the rightmost value. So the value of the
variable f is the return value of function g. g returns 2. So f is 2. Therefore
typeof f is “number”.
# Q9
var x = 1;
if (function f() {}) {
x += typeof f;
}
x;
In this question, we have to find the value of x at the end. When x is
defined, it is 1. Then there is an if block. It checks if “function f() ” is
truthy.
In JavaScript, a truthy value is a value that is considered true when encountered in a Boolean context. All values are truthy unless they are defined as falsy (i.e., except for false, 0, -0, 0n, "", null, undefined, and NaN).
So, the function is truthy. Now, typeof f gets added to x. Is that
"function"? That’s what I thought, at first. But turns out it’s not.
The Identifier in a FunctionExpression can be referenced from inside the FunctionExpression’s FunctionBody to allow the function to call itself recursively. However, unlike in a FunctionDeclaration, the Identifier in a FunctionExpression cannot be referenced from and does not affect the scope enclosing the FunctionExpression.
If you don’t understand (which is totally fine),
If the function is defined in the condition of if block, it’s a
FunctionExpression. The Identifier in the expression (which is the function
name, in this case, f), cannot be the referenced from that scope.
This means, variable f is undefined inside the if block.
# Q10 (Easiest in my opinion)
var x = [typeof x, typeof y][1];
typeof typeof x;
x is defined as the typeof y. y is, obviously undefined. So, x is
"undefined".
typeof x is string. typeof "string", is again, "string".
# Q11
(function (foo) {
return typeof foo.bar;
})({ foo: { bar: 1 } });
Another IIFE!
Inside the function, foo is equal to { foo: { bar: 1 }}. foo.bar is
obviously undefined. typeof undefined is, again, "undefined"
I don’t feel like this question is good enough to be put in this quiz.
# Q12
(function f() {
function f() {
return 1;
}
return f();
function f() {
return 2;
}
})();
IIFE again. Here a function named “f” is defined (which I will refer to as
f1). Inside the function, two functions are defined with the same name “f”.
The first function (which I will refer to as f2) returns 1. The second
function (which I will refer to as f3) returns 2.
Generally, JavaScript is interpreted. It is read and executed line by line, from
top to bottom. Based on this fact, you might have thought that the declaration
of f3 is unreachable, because, f1 returns early. And the return value would
be f2(). But that’s not the case here.
There is a thing called, “Function Hoisting”.
Function declarations in JavaScript are hoisted to the top of the enclosing function or global scope.
Because of this, f3 gets put after the f2 and before the return statement.
Now, when the interpreter start executing the code, f (inside the f1’s
scope), is set to f2 and then gets overridden by the f3. That’s why f()
returns 2.
# Q13
function f() {
return f;
}
new f() instanceof f;
The instanceof operator tests whether the prototype property of a constructor appears anywhere in the prototype chain of an object.
I didn’t understand it. Explain it to me, please.
# Q14
with (function (x, undefined) {}) length;
If you didn’t understand the with statement, see below.
The with statement extends the scope chain for a statement.
We can think the question like this (function(x, undefined)).length
It evaluates the function’s length. But what does Function.length return?
The length property indicates the number of parameters expected by the function.
In this case, The function expects 2 parameters. So the length property returns 2.
# Finally: Thank You!
I hope you find this explanation useful. Let me know if you have got any feedback.