请选择 进入手机版 | 继续访问电脑版
 找回密码
 立即注册

QQ登录

只需要一步,快速开始

搜索
开启左侧

这7个简单但答案并不显而易见的JavaScript面试问题,你会几个?

马上注册,分享更多源码,享用更多功能,让你轻松玩转云大陆。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
面试造飞机,工作拧螺丝。作为一个在软件开发和咨询行业摸爬滚打了多年的我,很多时候,对于很多面试中,出现这样令人不愉快的经历,也感觉到非常的不解和无奈。帮助这些人员,尽快的跨过这样的门槛,其实是一件“功德无量”的事情。毕竟,有时候,我们仅仅是想要一份工作而已,而不是想成为某个领域的“大神”,更不想去知道很多可能一辈子都不会接触到的一些语言细节。
好了,废话少说,今天就来总结7个在NodeJS/JavaScript开发人员(特别是高级开发人员)面试中,经常会被问到的问题,它们看起来都是如此的简单,但真正答好,有时候并不那么容易,好了,你会几个呢?
161611mqvcccu2i7ofibb6.jpg


问题1 : 意外的全局变量

仔细观察如下代码片段,问:变量 a 和 b 的类型(typeof)都是多少呢?
161611gavir6hz47lemhte.jpg


答案
你第一眼的答案,是不是a 和 b 的typeof都应该是undefined?毕竟,a和b都定义在函数foo内,属于该函数的局部变量。而现在却是在函数体外,来typeof这两个变量的。
让我们再仔细的来看一下第2行:
let a = b = 0
该语句确实声明了局部变量a。但是,它却声明了一个全局变量b。
区别在哪?其实仅仅是因为JavaScript的引擎,会将这样的一个语句,翻译为如下的两个语句:
b = 0;
let a = b;
看出问题来没?是的,其实重点就在于这个let(或者var),在现代的JavaScript语言中,只有使用let(或者var)来声明一个变量,才可以保证你所声明的变量,其作用域在你所“设想”它应该呆在的范围内。
因此,下面的这些语句中,变量的作用域范围,事实上都已经逃脱了你原先所认为的范围。
161612efy3ugzj73azap68.jpg


2. 数组长度的秘密

如下这段代码中,clothes[0]的值是什么?
161612v5ujjs1ukzcya5cy.jpg


答案
在JavaScript的数组长度属性中,隐藏着一个不经常被用到的秘密,那就是:
手动设置数组长度,具有增加/删除数组内元素的反作用
如上代码,显然的,当JavaScript执行clothes.length = 0时,系统将删除clothes数组的所有项目,此时,clothes[0]的值,应该是undefined
你猜对了么?
3. 鹰眼测试

仔细看一看,numbers数组的内容,应该是什么?
161612wctcfkocczdwotkf.jpg


答案
其实,我很讨厌有时候,出题人这样的“不怀好意”(当然,他们可能会把这个“美化”为他们需要关注细节的人才),在JavaScript的领域,这样的问题,数量还不够丰富,而在C/C++的领域,围绕着数组和指针,这样类型的考验,对很多面试者而言,简直就是一种折磨。
好吧,重点在哪里呢?嗯,是的,就是那个出现在花括号前的分号(;)
161612qfrlklylj9dlfd48.jpg


用一个简单的分号,就创建了一个不执行任何操作的空语句,而这是很容易被人所忽视的。因此,实际上,上面的代码,就等效于:将for()遍历执行空语句4次(不执行任何操作),然后......
161612fqgzapgv8ptq8ts8.jpg


所以,实际上,数组numbers只执行了一次push的操作,所以,numbers的值为:[ 5 ]
4. 换行也有意义?

如下代码所示,执行arrayFromValue(10)时,返回的值是什么?
161612bqso6uzcouc30f0v.jpg


答案
值是多少,你猜出来了么?
应该是undefined
怎么,你又没猜对?那我想,你可能是错过了return关键字和[item]表达式之间的这次换行了。
JavaScript不必需要一个分号作为一个语句的结束!
所以,在Prettier之类的工具的帮助下,我们几乎可以马上就让这一代码原形毕露。
161612c6cgk8am701mm611.jpg


答案自然也就呼之欲出了。
和对待很多其他的面试题目的态度不同,我对于这则精巧的题目很是喜欢,也经常拿它来用,因为,在我看来,这个问题,实实在在的告诉了我们,虽然关于JavaScript语句究竟是加,还是不加分号,才是最佳实践原则的争论由来已久,也都各有拥趸。但最坏的实践,肯定是混用风格
5. 棘手的关闭

控制台将输出什么?
161612b3hcg05jfogfo3jg.jpg


如果你对于闭包等概念没有很清楚的认识,那么,你猜对这道题目的答案的可能性会很低,或者你会猜,会依次输出0、1、2
毕竟,这应该是很多JavaScript初学者,最能想到的一种可能了。
答案
这的确不是一个很容易的问题,至少比起前面的4个来说。实际上,我们要好好的分析下,才能获得正确的答案。
总体来看,这段代码的执行,会经历两个阶段。

  • for() 语句会执行3次,每次迭代时,都会产生一个新的函数log,并发送给setTimout(),要求其安排执行这一新的log函数。
  • 第二阶段发生在100毫秒之后,3个预定需要执行的“不同”的log()函数被执行,此时,i的值,已经等于3了。
所以,整个执行的结果,应该是输出3、3、3
好吧,这里的关键,其实是要理解,在log闭包中,通过console.log(i)语句所输出的i,究竟所指为何。
留一个问题
那么,如果我希望通过类似上面的形式,依次输出0、1、2,应该怎样来修改上面的这段代码呢?
6. 讨厌的浮点数

161613mqh3h5553yjjn75h.jpg


true还是false?
答案
这可能是最没有困扰的一个问题了,我想。大部分人应该都会回答:false,只要他/她接触过编程。
因为是以二进制形式编码,因此像浮点数相加之类的操作,总会产生舍入误差,JavaScript也无法免俗。
在JavaScript下,这个值约略等于:0.30000000000000004,所以,自然的,相等的判断就不会成立。
7. 临时死区和变量提升

最后的问题:看看下面的这段代码,你觉得它会输出什么呢?
161613eguqf0ueorqqiiwi.jpg


问题很简单,就是如果在声明这两个变量myVarmyConst前,就访问和使用了这两个变量,会发生什么?
我的经验是,至少60%以上的人,会答错!
答案
这里实际上涉及到了JavaScript作为一种语言,非常独特的两个概念,即:临时死区变量提升。而这两个概念,又将深深的影响JavaScript变量,在其整个生命周期中的表现。
161613j54zwccotrw84yt7.jpg


如图所示,当变量声明前,试图访问最后借助let或者const声明的变量,和访问最后通过var声明的变量,其在表现上是不同的。
回到我们的问题,就是

  • myVar一开始会处在变量提升区,因此,其值会返回undefined
  • 而myConst由于其处在临时死区,所以,对该变量的提前访问,会引发一个JavaScript的系统错误。
你GET到这一点了么?
一个简单的总结

还是那句话,我并不认为,这些面试问题,会对你的实际开发能力的提升有多少帮助,在一个开发的团队中,借助于相应的开发规范,实际上会避免很多这样“带有迷惑性”问题的产生。
当然,其中部分的问题,的确可以有效的评估到您,对于JavaScript的语法是否熟悉,但也仅此而已。
在后续的文章中,我也将就这些问题,比如闭包的问题,比如临时死区和变量提升的问题等等,其背后所涉及的相关JavaScript语法现象,做进一步的解读,希望可以给去面试相关工作的人以一定的帮助。
好的,今天就到这里了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

  • 0 关注
  • 0 粉丝
  • 4 帖子
广告招商