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.
(function(){
return typeof arguments;
})();
Thearguments
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.
Onlystring
will be returned fromtypeof
operator. And following table summarizes the possible return values oftypeof
.
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 knowarguments
can only be detected as"object"
.
var f = function g(){ return 23; };
typeof g();
It is a function expression of a function namedg
assigned to the variablef
.
There is a distinction between function nameg
and variablef
the function is assigned to.
The function nameg
cannot be changed, while the variable the function is assigned to can be reassigned. The function nameg
can be used only within the function's body. Attempting to use it outside the function's body results in an error.
(function(x){
delete x;
return x;
})(1);
Thedelete
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 deletingx
variable.
> And you may need to know, thedelete
operator has nothing to do with directly freeing memory (it only does indirectly via breaking references)
var y = 1, x = y = typeof x;
x;
Thinking of this quiz in two separate steps:Thevar y = 1; //step 1 var x = y = typeof x; //step 2
step 1
is precise. Let's see howstep 2
works:
- The assignment expression is evaluated from
right
toleft
y
is reassigned to(typeof x)
which is"undefined"
x
is assigned to the result from last expression(y = typeof x)
which is"undefined"
(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; });
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. Soarguments[0]
gets the value of the function passed in, not its reference, which meansthis
inbar
points toglobal
(window
in browser envs) object, and there is nobaz
property on it.
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 offoo.bar
, not its reference, sothis
in it will not point to the objectfoo
, but globalwindow
instead.
var f = (function f(){ return '1'; }, function g(){ return 2; })();
typeof f;
Thecomma operator
evaluates each of its operands (from left to right) and returns the value of the last operand.
So functiong
returned from(function f(){ return '1'; }, function g(){ return 2; })
, while it gets called, number2
is returned.
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.
var x = [typeof x, typeof y][1];
typeof typeof x;
typeof y
returns"undefined"
since no variabley
is defined before.x
is assigned totypeof y
(which is"undefined"
)typeof x
is"string"
typeof typeof x
is"string"
(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 } });
(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(); })();
function f(){ return f; }
new f() instanceof f;
When the codenew f()
is executed, the following things happen:Since function is also some sort of
- A new object is created, inheriting from
f.prototype
- The constructor function
f
is called with the specifiedarguments
andthis
bound to the newly created object.new f
is equivalent tonew f()
, i.e. if no argument list is specified,f
is called withoutarguments
.- 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.
object
, sonew f()
returnsf
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.
with (function(x, undefined){}) length;
Thewith
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.
Solength
will be detected in the expression ofwith
first, while the function object containslength
property, which indicates the number of formal parameters.