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;
})();
Theargumentsis an Array-like object corresponding to the arguments passed to a function. Which means you can use it in all functions without defining explicitly.
Onlystringwill be returned fromtypeofoperator. 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 knowargumentscan only be detected as"object".
var f = function g(){ return 23; };
typeof g();
It is a function expression of a function namedgassigned to the variablef.
There is a distinction between function namegand variablefthe function is assigned to.
The function namegcannot be changed, while the variable the function is assigned to can be reassigned. The function namegcan 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);
Thedeleteoperator removes a property from an object.
The correct usage as following:delete object.property delete object['property']
deleteis only effective on an object's properties. It has no effect on variable or function names. Which means nothing will happen while deletingxvariable.
> And you may need to know, thedeleteoperator 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 2step 1is precise. Let's see howstep 2works:
- The assignment expression is evaluated from
righttoleftyis reassigned to(typeof x)which is"undefined"xis 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 meansthisinbarpoints toglobal(windowin browser envs) object, and there is nobazproperty 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, sothisin it will not point to the objectfoo, but globalwindowinstead.
var f = (function f(){ return '1'; }, function g(){ return 2; })();
typeof f;
Thecomma operatorevaluates each of its operands (from left to right) and returns the value of the last operand.
So functiongreturned from(function f(){ return '1'; }, function g(){ return 2; }), while it gets called, number2is 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 yreturns"undefined"since no variableyis defined before.xis assigned totypeof y(which is"undefined")typeof xis"string"typeof typeof xis"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
fis called with the specifiedargumentsandthisbound to the newly created object.new fis equivalent tonew f(), i.e. if no argument list is specified,fis 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()returnsfitself, not the created instance.The expression
a instanceof bwill check if b is in a's prototype chain, no matter at what level it is.
with (function(x, undefined){}) length;
Thewithstatement 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.
Solengthwill be detected in the expression ofwithfirst, while the function object containslengthproperty, which indicates the number of formal parameters.