/ 昌里大金猪的空间 / 浅析 kangax 提出的 Javascript quiz

浅析 kangax 提出的 Javascript quiz

2011-05-10 posted in [javascript]

Javascript quiz一文是JS大师kangax一年前发表的,网上仔细找找应该有不少关于此文的分析。在此我想炒个冷饭,根据对JS的理解与现有经验尝试作出自己的分析。如有分析不到位的地方,恳请指正。


代码片段一

  1. (function(){  
  2.     return typeof arguments;  
  3. })();  
// "object"
本题考察arguments对象。arguments是Array-like对象,并不是Array,它的__proto__指向Object,参考Javascript Object Layout

代码片段
  1. var f = function g(){  
  2.     return 23;  
  3. };  
  4. typeof g();  
// “number”或者浏览器报语法错误
本题考察函数表达式与函数声明,两者关系十分微妙。类似于lifesinger以前出过的一道“大”题目(lifesinger blog原文数据已丢失),由于篇幅问题在此不作细述,强烈建议读者仔细研读本题中的参考资料。

  代码片段三
  1. (function(x){  
  2.     delete x;  
  3.     return x;  
  4. })(1);  
// 1
本题考察delete运算符。根据MDCIf expression does not evaluate to a property, delete does nothing.Some object properties cannot be deleted. In the ECMA 262 specification these are marked as DontDelete.The delete operator returns false only if the property exists and cannot be deleted. It returns true in all other cases. 此处的x实际上是arguments,属性为DontDelete想深入了解delete细节,参考Understanding delete

代码片段
  1. var y = 1, x = y = typeof x;  
  2. x;  
// "undefined"
本题考察变量声明以及运算顺序。根据JavaScript中的作用域与变量声明提升,上面这段代码实际上等同于
  1. var y, x;       //  y=undefined,x=undefined  
  2. y = 1;          //  y=1  
  3. y = typeof x;  //  y="undefined"  
  4. x = y;          //  x="undefined"  

代码片段
  1. (function f(f){  
  2.     return typeof f();  
  3. })(function(){return 1;});  
// “number”
本题考察函数执行环境问题。当首次载入JS代码时创建一个全局执行环境,每调用一个新的JS函数就会进入相应的执行环境,并且函数调用期间都处于各自的环境中,构成了一个执行环境栈。具体参考理解Javascript_12_执行模型浅析

代码片段
  1. var foo = {  
  2.     bar: function(){return this.baz;},  
  3.     baz: 1  
  4. };  
  5. (function(){  
  6.     return typeof arguments[0]();  
  7. })(foo.bar);  
// “undefined”
本题考察对象作用域。foo.bar中的this实际上指向window对象,并不是foo对象本身。

代码片段七
  1. var foo = {  
  2.     bar: function(){return this.baz;},  
  3.     baz: 1  
  4. }  
  5. typeof (f = foo.bar)();  
// “undefined”
本题考察对象作用域,与上题类似。其中, (f = foo.bar)();实际上等同于typeof (foo.bar)();

代码片段八
  1. var f = (function f(){return "1";}, function g(){return 2;})();  
  2. typeof f;  
// "number"
本题考察函数运算符,)中声明了两个函数。其中充当连续运算符的角色。(function f(){return "1";}, function g(){return 2;})返回值是后的函数值。

代码片段九
  1. var x = 1;  
  2. if (function f(){}) {  
  3.     x += typeof f;  
  4. }  
  5. x;  
// "1function"或者“1undefined”
本题考察条件表达式与函数表达式。与代码片段二的基本原理类似,由于函数表达式造成不同浏览器下的结果值不同。

代码片段十
  1. var x = [typeof x, typeof y][1];  
  2. typeof typeof x;  
// "string"
本题考察typeof。第一行代码实际上等同于var x = typeof y; 此时x为"undefined"。typeof "undefined"的值为"string",typeof "string"的值仍旧为"string"。

代码片段十一
  1. (function(foo){  
  2.     return typeof foo.bar;  
  3. })({foo: {bar: 1}});  
// "undefined"
本题考察对象。参数foo为{foo: {bar: 1}},于是foo.foo的值为{bar: 1},foo.bar;的值为undefined。

代码片段十二
  1. (function f(){  
  2.     function f(){return 1;}  
  3.     return f();  
  4.     function f(){return 2;}  
  5. })();  
// 2
本题考察函数声明,实际上还是Javascript Hoisting的问题,后定义的函数覆盖先前的函数。

代码片段十三
  1. function f(){  
  2.     return f;  
  3. }  
  4. new f() instanceof f;  
// false
本题考察prototype与constructor。再看一下Javascript Object Layout,a instanceof b实际上是顺着a对象的__proto__一直往上找所有构造函数的原型对象。本题第二行将返回值并不是原先期望的默认的constructor对象,对先前Javascript Object Layout关系图造成混乱。

代码片段十四
  1. with (function(x, undefined){}) length;