关于一道JS面试题的思考
题目:
for (var i = ; i < ; i++) {
setTimeout(function() {
console.log(new Date, i);
}, );
}
console.log(new Date, i);
1、面对这段代码时给出的结果也不尽相同,以下是典型的答案:
A. 20% 的人会快速扫描代码,然后给出结果:0,1,2,3,4,5;
B. 30% 的人会拿着代码逐行看,然后给出结果:5,0,1,2,3,4;
C. 50% 的人会拿着代码仔细琢磨,然后给出结果:5,5,5,5,5,5;
只要你对 JS 中同步和异步代码的区别、变量作用域、闭包等概念有正确的理解,就知道正确答案是 C,代码的实际输出是:

2、如果我们约定,用箭头表示其前后的两次输出之间有 1 秒的时间间隔,而逗号表示其前后的两次输出之间的时间间隔可以忽略,代码实际运行的结果该如何描述?会有下面两种答案:
A. 60% 的人会描述为:5 -> 5 -> 5 -> 5 -> 5,即每个 5 之间都有 1 秒的时间间隔;
B. 40% 的人会描述为:5 -> 5,5,5,5,5,即第 1 个 5 直接输出,1 秒之后,输出 5 个 5;
这就要求候选人对 JS 中的定时器的工作机制非常熟悉,循环执行过程中,几乎同时设置了 5 个定时器,一般情况下,这些定时器都会在 1 秒之后触发,而循环完的输出是立即执行的,显而易见,正确的描述是 B。
3、追问:闭包
如果这道题仅仅是考察候选人对 JS 异步代码、变量作用域的理解,局限性未免太大,接下来如果期望代码的输出变成:5 -> 0,1,2,3,4,该怎么改造代码?熟悉闭包的同学很快能给出下面的解决办法:
for (var i = ; i < ; i++) {
(function(j){
setTimeout(function() {
console.log(new Date, j);
}, );
})(i);
}
console.log(new Date, i);
巧妙的利用 IIFE(Immediately Invoked Function Expression:声明即执行的函数表达式)来解决闭包造成的问题,确实是不错的思路,但是初学者可能并不觉得这样的代码很好懂,至少笔者初入门的时候这里琢磨了一会儿才真正理解。
有没有更符合直觉的做法?答案是有,我们只需要对循环体稍做手脚,让负责输出的那段代码能拿到每次循环的 i 值即可。该怎么做呢?利用 JS 中基本类型(Primitive Type)的参数传递是按值传递(Pass by Value)的特征,不难改造出下面的代码:
var output = function(i){
setTimeout(function() {
console.log(new Date, i);
}, );
}
for (var i = ; i < ; i++) {
output(i);//值传递传个i值过去
}
console.log(new Date, i);
4、追问
如果期望代码的输出变成 0 -> 1 -> 2 -> 3 -> 4 -> 5,并且要求原有的代码块中的循环和两处 console.log 不变,该怎么改造代码?新的需求可以精确的描述为:代码执行时,立即输出 0,之后每隔 1 秒依次输出 1,2,3,4,循环结束后在大概第 5 秒的时候输出 5(这里使用大概,是为了避免钻牛角尖的同学陷进去,因为 JS 中的定时器触发时机有可能是不确定的)
for (var i = ; i < ; i++) {
(function(j) {
setTimeout(function() {
console.log(new Date, j);
}, * j); // 这里修改 0~4 的定时器时间
})(i);
}
setTimeout(function() { // 这里增加定时器,超时设置为 5 秒
console.log(new Date, i);
}, * i);

不得不承认,这种做法虽粗暴有效,但是不算是能额外加分的方案。如果把这次的需求抽象为:在系列异步操作完成(每次循环都产生了 1 个异步操作)之后,再做其他的事情,代码该怎么组织?聪明的你是不是想起了什么?对,就是 Promise。
ES6、ES7的解决方案(后续)。
关于一道JS面试题的思考的更多相关文章
- new与属性访问的顺序,从一道JS面试题说起
这段时间一直在研究设计模式,在看工厂模式的时候,看到一段代码 VehicleFactory.prototype.createVehicle = function ( options ) { if( o ...
- 一道JS面试题引发的血案
刚入职新公司,属于公司萌新一枚,一天下午对着屏幕看代码架构时. BI项目组长给我看了一道面试别人的JS面试题. 虽然答对了,但把理由说错了,照样不及格. 话不多说,直接上题: var a = 1; s ...
- 一道JS面试题所引发的"血案",透过现象寻本质,再从本质看现象
觉得本人写的不算很烂的话,可以登录关注一下我的GitHub博客,新手写东西写的不好之处,还望见谅,毕竟水平有限,写东西只为交流提高,一起学习,还望大神多加指点,指出纰漏,和提出宝贵的意见,博客会坚持写 ...
- 一道js面试题看变量的作用域
[问题]分别求下面程序的输出结果: 1. <script type="text/javascript"> var a = 10; sayHi(); function s ...
- 一道js面试题
当然这道面试题并不一定就能在你面试的时候遇到,但是不怕一万就怕万一,会的多一些还是好的. 问:怎么判断一串字符中哪个字符出现的最多,最多几次或者这串字符分别有哪些,每个字符出现了几次.写你请出运算代 ...
- 腾讯的一道js面试题(原型)
有一只小狗叫花花,它会“汪汪”叫,他的同伴也会汪汪叫,后来环境发生了变化,新出生的狗不会再“汪汪”叫,而变成“呜呜”叫. 试通过继承来达到目的 function Dog(){ 2 this.bark ...
- 一道经典JS面试题
超过80%的候选人对下面这道JS面试题的回答情况连及格都达不到.这究竟是怎样神奇的一道JS面试题?他考察了候选人的哪些能力?对正在读本文的你有什么启示? 不起眼的开始 招聘前端工程师,尤其是中高级前端 ...
- 一道经典的js面试题
# 声明:学习编程语言最好的方式就是通过实例学习 ## 下面是我在博客上看到的一道js面试题,可以说非常经典,下面会以最简单的方式让你理解题目:```bashfunction Foo() { getN ...
- 那晚征服的一道js经典的面试题
今天朋友共享了一道js中经典的面试题,需求是这样的 给定你任意一个字符串,让你写出一个算法,求算出该字符串中出现次数最多的一个字符,并将其结果输出 刚拿到这道题的第一感觉便是定义一个count计时器, ...
随机推荐
- Python 递归删除非空目录(包括子目录以及文件)
Python的OS模块自带rmdir和removedirs函数用于删除目录,但是两者都不能删除非空目录,以下代码定义了一个函数 remove_dir 用于删除非空目录. #作者官网 http://ww ...
- iOS Sprite Kit教程之滚动场景
iOS Sprite Kit教程之滚动场景 滚动场景 在很多的游戏中,场景都不是静止的,而是滚动的,如在植物大战僵尸的游戏中,它的场景如图2.26所示. 图2.26 植物大战僵尸 在图2.26中,用 ...
- python2和python3同时安装
现在很多项目用python2完成的,很多情况下2和3是同时存在的 大多人都是先安装了python2 安装python3: 下一步: 然后安装完成以后,去cmd控制台输入python看看安装成功了吗(用 ...
- 在Windows上安装FFmpeg程序
原文地址:http://helloway.blog.51cto.com/7666282/1642247 FFmpeg是一套可以用来记录.转换数字音频.视频,并能将其转化为流的开源计算机程序.它提供了录 ...
- 清北冬令营入学测试[ABCDEF]
http://tyvj.cn/Contest/861 [1.2.2017] 像我这种蒟蒻只做了前6道还有道不会只拿了暴力分 A 描述 这是一道有背景的题目,小A也是一个有故事的人.但可惜的是这里纸张太 ...
- [BZOJ4811][YNOI2017]由乃的OJ(树链剖分+线段树)
起床困难综合症那题,只要从高往低贪心,每次暴力跑一边看这一位输入0和1分别得到什么结果即可. 放到序列上且带修改,只要对每位维护一个线段树,每个节点分别记录0和1从左往右和从右往左走完这段区间后变成的 ...
- 【线性基】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem A. XOR
题意:给你一些数,问你是否能够将它们划分成两个集合,使得这两个集合的异或和之差的绝对值最小. 设所有数的异或和为S,集合A的异或和为A. 首先,S的0的位对答案不造成影响. S的最高位1,所对应的A的 ...
- 高并发系列之——负载均衡,web负载均衡
1 前言 负载均衡,一般包含两方面的含义.一方面是,将单一的重负载分担到多个网络节点上做并行处理,每个节点处理结束后将结果汇总返回给用户,这样可以大幅提高网络系统的处理能力: 第二个方面的含义是,将大 ...
- 【BZOJ】2760: [JLOI2011]小A的烦恼【字符串模拟】
2760: [JLOI2011]小A的烦恼 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 406 Solved: 258[Submit][Statu ...
- SGU 403 Game with points
408. Game with points Time limit per test: 0.25 second(s)Memory limit: 65536 kilobytes input: standa ...