JavaScript Quiz

在国外的一篇博客文章上有下面一些题目,刚开始做的时候错了4个,虽然涉及的知识点不算非常多,但的确有很多细节方面平时需要多加注意的,现在记录下每个题目背后所需要的知识。

 Quiz mainly focuses on knowledge of scoping, function expressions (and how they differ from function declarations), references, process of variable and function declaration, order of evaluation, and a couple more things like  delete  operator and object instantiation. 

以下结果在 jsfiddle 以及Chrome上进行了测试。

首先,了解在 ECMAScript 5th edition[1]中说明的JavaScript的数据类型 ,其中简单类型包括 数字、字符串、布尔值(true 和 false)、null 值和 undefined 值。其他所有的值都是对象 Object (包括 Array Date RegExp Function 等)。

然后,知道typeof 方法的值及其所对应的返回结果:

1.

 (function(){ return typeof arguments; })();

Answer: "object"

arguments 在JavaScript 中是对象的一个特殊属性,返回的是object类型。

2.

  var f = function g(){ return 23; };
  typeof g();

Answer: Error[2]

以表达式方式定义的函数,函数名称是可选的。

如果一个函数定义表达式包含函数名称,函数的局部作用域将会包含一个绑定到函数对象的名称;函数的名称将成为函数内部的一个局部变量,可在函数内进行调用以实现递归操作。

3.

  (function(x){
    delete x;
    return x;
  })(1);

Answer: 1

 delete 运算符,是一元运算符,它用来删除对象属性或者数组元素,当删除属性或者删除数组元素时不仅仅是设置了一个undefined 的值;当删除一个属性时,这个属性将不再存在,读取一个不存在的属性将返回undefined,但是可以通过 in 运算符来检测这个属性是否在对象中存在。

Notice: delete 希望它的操作数是一个左值,如果它不是左值,那么delete 将不进行任何操作同时返回true。否则,delete 将试图删除这个指定的左值。如果删除成功,delete 将返回true. 然而并不是所有的属性都可删除,一些内置核心和客户端属性是不能删除的,用户通过var 语句声明的变量是不能删除的,通过function 语句定义的函数和函数参数也不能删除。

左值: 表达式只能出现在赋值运算符的左侧。在JavaScript中,变量、对象属性和数组元素均是左值。ECMAScript规范允许内置函数返回一个左值,但自定义的函数则不能返回左值。

4.

  var y = 1, x = y = typeof x;
  x;

 Answer: "undefined"

x = y = typeof x  等价于 x = (y = (typeof x)) , 运算顺序从右至左

5.

  (function f(f){
    return typeof f();
  })(function(){ return 1; });

Answer: "number"

 这道题目做错了,后面在浏览器和JSHint下测试了会也不得其解,求助同学后终于想通了···+_-

这里的函数名与函数的形参名称一样,在JSHint下会提示 "f" is already defined , 在Chrome中没有报错,最后返回的是“number”。

因为当函数名与形参一致的时候 return typeof f(); 中的 f 是形参f 不是 函数名f(为什么?),所以f() 就相当于 (function(){ return 1;})() 。

而当形参与函数名f 不一致,但函数中仍然是return typeof f() 的时候,JSHint 没有提示错误,执行后浏览器最后会报错:Uncaught RangeError: Maximum call stack size exceeded 。

以后在写函数的时候要注意 函数名与形参 的命名。

6.

  var foo = {
    bar: function() { return this.baz; },
    baz: 1
  };
  (function(){
    return typeof arguments[0]();
  })(foo.bar);

Answer: "undefined" 

7.

  var foo = {
    bar: function(){ return this.baz; },
    baz: 1
  }
  typeof (f = foo.bar)();

Answer: "undefined"

 这两题有相似的地方,第六题按我的理解是把实参 foo.bar 赋值给了 arguments[0], 第七题则是赋值给 f; 

重新赋值后变量中的 this 指向的都是全局对象,调用方法属于全局调用,因此返回的类型都是“undefined”

8.

  var f = (function f(){ return "1"; }, function g(){ return 2; })();
  typeof f;

Answer:  

 逗号运算符:首先计算左操作数,然后计算右操作数,最后返回右操作数的值。

9.

  var x = 1;
  if (function f(){}) {
    x += typeof f;
  }
  x;

Answer: "1undefined"

 函数定义返回的是一个新的Function对象,在if 语句里返回的是true;这里的函数f 的作用范围仅在if 语句的条件判断 if() 内,typeof f 中的f 仍然是undefined 。

备注:函数声明语句通常出现在JavaScript代码的最顶层,也可以嵌套在其他函数体内。但在嵌套时,函数声明只能出现在所嵌套函数的顶部。也就是说,函数定义不能出现在if 语句、while循环或其他任何语句中,正是由于函数声明位置的这种限制, ECMAScript标准规范并没有将函数声明归类为真正的语句。 像这种将函数声明放在其他语句内的做法并不具备可移植性。

10.

  var x = [typeof x, typeof y][1];
  typeof typeof x;

Answer: "string"

 这里x 是一个数组的第二个元素,等价于 typeof y ,即:"undefined" , typeof x 即:"string"

如果 题目是 var x = [typeof x , typeof y][2];  的话,x 则是undefined , typeof x 为"undefined"

11.

  (function(foo){
    return typeof foo.bar;
  })({ foo: { bar: 1 } });

Answer: "undefined"

返回值中的foo即是形参中的foo, 所以最后返回相当于 typeof {foo: {bar: 1}}.bar 。

12.

  (function f(){
    function f(){ return 1; }
    return f();
    function f(){ return 2; }
  })();

Answer: 2

 这里最外面的函数内定义了两个函数,不论return 的位置在哪里,都会先执行函数定义语句(定义式函数被提前),因此这个例子中的同名函数前一个函数总是会被后一个函数所覆盖。

13.

  function f(){ return f; }
  new f() instanceof f;

Answer: false

 这里 function f(){...}中的 return f 导致了 结果为false 。(WHY?

instanceof 运算符希望左操作数是一个对象,右操作数标识对象的类。如果左侧的对象是右侧对象的实例,则表达式返回true;否则返回false。

有关instanceof 更深入的理解

14.

  with (function(x, undefined){}) length;

Answer: 2 ( 没用到过with -_-||)

原网站给出的正确结果为 2 , 但在JSHint 下提示错误,Chrome下亦没有出现结果(求解)。

[1]: quiz的作者是基于3rd edition的,我是看的5th edition, 在quiz中没发现有什么问题。

[2]: "Error" in answer indicates that overall snippet results in a runtime error .

参考资料: JavaScript权威指南、ECMAScript 5th Edition、JavaScript Pattern、JavaScript: The Good Parts

原文地址:https://www.cnblogs.com/stonewong/p/3594072.html