下面这几道 JavaScript 题目大多来自于周五的一个小分享。都是很小的题目,但是很容易犯错。有一些是语言特性使然,有一些则是语言本身没有设计好而留下的陷阱。结果就是,遇到的人很容易陷进去骂娘,这些东西是略有些反直觉,感兴趣的不妨看看,平时我们还是尽量少些这样似是而非的代码。
1.
function Container( properties ) { var objthis = this; for ( var i in properties ) { (function(){ var t = properties[i]; objthis[ "get" + i ] = function() {return t;}; objthis[ "set" + i ] = function(val) {t = val;}; })(); } } var prop = {Name : "Jim", Age : 13}; var con = new Container(prop); console.log(con.getName()); con.setName("Lucy"); console.log(con.getName()); console.log(prop.Name);
这段代码会输出什么?前面两行分别是“Jim” 和“Lucy”,这不会有问题;但是第三行应该输出的是“Jim”,但是有的人会误认为 prop 对象已被修改,故输出“Lucy”。其实在匿名函数中,properties[i] 的值已经赋给了临时变量 t,之后闭包对于外部变量的引用完全由 t 这个媒介来完成,因此 prop 传入以后并未发生任何属性的更改。
2.
function a (x) { return x * 2; } var a; console.log(a);
这段代码中,其实 var a 并没有任何影响,输出的是 a(x) 这样的方法签名。
3.
c = 999; var c = 888; console.log(this.c); //① function b (x, y, c) { c = 6; arguments[2] = 10; console.log(c); //② console.log(this.c); //③ var c = 6; console.log(c); //④ console.log(this.c); //⑤ } b(1, 2, 3, 4);
这道题是比较变态的。
- 第①处,this 指的是 window,在 window 下,c、this.c、var c 在这里指的是同一个东西,看透这一点就好办了。打印的是 888。
- 第②处,方法体中,参数 c 和 arguments[2] 指的是同一个地址,所以把后者赋为 10 的时候,打印的是 10,不是 6。
- 第③处,this 指的是 window,打印的是 888。
- 第④处,打印的是 6。
- 第⑤处,打印的是 888。
4.
var start = new Date(); setTimeout( function(){ var end = new Date(); console.log(end - start); }, 1000 ); while(new Date() - start < 2000);
JavaScript 因为是单线程工作的,因此虽然回调函数设置了 1000 毫秒后执行,事实上在 1000 毫秒的时候根本得不到执行,等待到 while 循环执行完毕后(因此已经是 2000 毫秒以后了),才去执行,因此输出应该是一个大于 2000 的数字。
5.
(function(){ console.log(typeof arguments); })();
很多人会说打印的是 array,其实,typeof 根本不会打印 array 的啊,打印的是 object。
6.
function a(){return a;} console.log(new a() instanceof a);
应该打印的是 false,其实原因很简单,new a() 的时候,因为 return 语句,得到的不是 a 的实例,而是 a 本身,a instanceof a 当然是 false 啦。
最后,还有一个小题目是关于 Function Invocation Pattern 的,我在这篇文章里有写到,就不单独贴出来了。
文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《四火的唠叨》
题目四,会输出两个值,第一个是很小的值,第二个是个大于 2000 的值。
chrome 和 firefox 下都试了下,确实会输出 2 个值,但是想不到原因
setTimeout 会返回一个 id
因为 return a;
new a() === a //结果 true
———————————————————-
参见《JavaScript 的 5 种调用函数的方法》http://www.cnblogs.com/lhb25/archive/2009/03/12/1409241.html
所谓的陷阱就是闭包和作用域。。。
说的太有道理啦。
所谓的陷阱是相对于不了解 ECMAScript 的人而言。不过大多数用 JS 的人还真不了解。
第 6 个表示不理解,为什么呢?
我看到这些题目就想起了中学时候考试的题目,所谓陷阱题。
仿佛老师出这些题的目的就是让你做错……
我认为老师出陷阱题目的不是让你做错,而是让你更深刻的理解。
但是有的时候往往错的那个记得反而更清楚……
其实我想说的是考试和现实生活中的差距。上面任何一段代码出现在你的现实项目里,你敢说你不会骂人吗?
题目 4
“ 毁掉” -> “ 回调”
谢谢。已修正。