Quiz Legend

by Want contribute to this document?
Background

Recently, many front-end developers were shocked by kangax's Javascript quiz. Since JavaScript is a dynamic programming language and the standards are not well implemented in all runtime environment. You probably have no idea about "What happened to those quiz?", "What the hell is the execution result?"

Let's try to figure out the magic behind.

Question 1
(function(){
    return typeof arguments;
})();
    
The arguments is an Array-like object corresponding to the arguments passed to a function. Which means you can use it in all functions without defining explicitly.

Only string will be returned from typeof operator. And following table summarizes the possible return values of typeof.
Type Result
Undefined "undefined"
Null "object"
Boolean "boolean"
Number "number"
String "string"
Symbol (new in ECMAScript 2015) "symbol"
Host object (provided by the JS environment) Implementation-dependent
Function object (implements [[Call]] in ECMA-262 terms) "function"
Any other object "object"

According to above summary, we know arguments can only be detected as "object".
Question 2
var f = function g(){ return 23; };
typeof g();
    
It is a function expression of a function named g assigned to the variable f.
There is a distinction between function name g and variable f the function is assigned to.

The function name g cannot be changed, while the variable the function is assigned to can be reassigned. The function name g can be used only within the function's body. Attempting to use it outside the function's body results in an error.
Question 3
(function(x){
    delete x;
    return x;
})(1);
    
The delete operator removes a property from an object.

The correct usage as following:
delete object.property
delete object['property']

delete is only effective on an object's properties. It has no effect on variable or function names. Which means nothing will happen while deleting x variable.

> And you may need to know, the delete operator has nothing to do with directly freeing memory (it only does indirectly via breaking references)
Question 4
var y = 1, x = y = typeof x;
x;
    
Thinking of this quiz in two separate steps:
var y = 1; //step 1
var x = y = typeof x; //step 2
The step 1 is precise. Let's see how step 2 works:
  1. The assignment expression is evaluated from right to left
  2. y is reassigned to (typeof x) which is "undefined"
  3. x is assigned to the result from last expression (y = typeof x) which is "undefined"
Question 5
(function f(f){
    return typeof f();
})(function(){ return 1; });
    
(function f(f){
    //f here is the function passed in
    //and the result of f() is 1
    return typeof f(); //So typeof 1 return "number"
})(function(){ return 1; });
Question 6
var foo = {
    bar: function() { return this.baz; },
    baz: 1
};

(function(){
    return typeof arguments[0]();
})(foo.bar);
    
You may get it wrong here with the result of "number". Params passed into a function can be treated as assignment. So arguments[0] gets the value of the function passed in, not its reference, which means this in bar points to global(window in browser envs) object, and there is no baz property on it.
Question 7
var foo = {
    bar: function(){ return this.baz; },
    baz: 1
}
typeof (f = foo.bar)();
    
This is very similar with previous quiz. The expression (f = foo.bar) returns the value of foo.bar, not its reference, so this in it will not point to the object foo, but global window instead.
Question 8
var f = (function f(){ return '1'; }, function g(){ return 2; })();
typeof f;
    
The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.

So function g returned from (function f(){ return '1'; }, function g(){ return 2; }), while it gets called, number 2 is returned.
Question 9
var x = 1;
if (function f(){}) {
    x += typeof f;
}
x;
    
The key point is the same as Question 2. Function name f can not be reached from outside of the function body.
Question 10
var x = [typeof x, typeof y][1];
typeof typeof x;
    
  1. typeof y returns "undefined" since no variable y is defined before.
  2. x is assigned to typeof y(which is "undefined")
  3. typeof x is "string"
  4. typeof typeof x is "string"
Question 11
(function(foo){
    return typeof foo.bar;
})({ foo: { bar: 1 } });
    
This is just a visual trick
(function(foo){
    //the foo here is the passed in object itself, not the foo property defined in that object
    return typeof foo.bar;
})({ foo: { bar: 1 } });
Question 12
(function f(){
    function f(){ return 1; }
    return f();
    function f(){ return 2; }
})();
    
A function defined by a function declaration can be used before the function declaration itself. This behavior we call it "hoisting", so the code after compilation looks as following:
(function f(){
    function f(){ return 1; }
    function f(){ return 2; }
    return f();
})();
Question 13
function f(){ return f; }
new f() instanceof f;
    
When the code new f() is executed, the following things happen:
  1. A new object is created, inheriting from f.prototype
  2. The constructor function f is called with the specified arguments and this bound to the newly created object. new f is equivalent to new f(), i.e. if no argument list is specified, f is called without arguments.
  3. The object returned by the constructor function becomes the result of the whole new expression. If the constructor function doesn't explicitly return an object, the object created in step 1 is used instead.
Since function is also some sort of object, so new f() returns f itself, not the created instance.

The expression a instanceof b will check if b is in a's prototype chain, no matter at what level it is.

Question 14
with (function(x, undefined){}) length;
    
The with statement adds the given object to the head of this scope chain during the evaluation of its statement body. If an unqualified name used in the body matches a property in the scope chain, then the name is bound to the property and the object containing the property. Otherwise a ReferenceError is thrown.

So length will be detected in the expression of with first, while the function object contains length property, which indicates the number of formal parameters.
I hope you enjoy this post, in case you want to star our effort, try click here:   Star