龙空技术网

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

纸飞机技术拆解局 557

前言:

今天大家对“js语法烂”大体比较关切,看官们都需要学习一些“js语法烂”的相关知识。那么小编也在网摘上网罗了一些关于“js语法烂””的相关文章,希望朋友们能喜欢,大家一起来了解一下吧!

面试造飞机,工作拧螺丝。作为一个在软件开发和咨询行业摸爬滚打了多年的我,很多时候,对于很多面试中,出现这样令人不愉快的经历,也感觉到非常的不解和无奈。帮助这些人员,尽快的跨过这样的门槛,其实是一件“功德无量”的事情。毕竟,有时候,我们仅仅是想要一份工作而已,而不是想成为某个领域的“大神”,更不想去知道很多可能一辈子都不会接触到的一些语言细节。

好了,废话少说,今天就来总结7个在NodeJS/JavaScript开发人员(特别是高级开发人员)面试中,经常会被问到的问题,它们看起来都是如此的简单,但真正答好,有时候并不那么容易,好了,你会几个呢?

问题1 : 意外的全局变量

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

答案

你第一眼的答案,是不是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)来声明一个变量,才可以保证你所声明的变量,其作用域在你所“设想”它应该呆在的范围内。

因此,下面的这些语句中,变量的作用域范围,事实上都已经逃脱了你原先所认为的范围。

2. 数组长度的秘密

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

答案

在JavaScript的数组长度属性中,隐藏着一个不经常被用到的秘密,那就是:

手动设置数组长度,具有增加/删除数组内元素的副作用

如上代码,显然的,当JavaScript执行clothes.length = 0时,系统将删除clothes数组的所有项目,此时,clothes[0]的值,应该是undefined。

你猜对了么?

3. 鹰眼测试

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

答案

其实,我很讨厌有时候,出题人这样的“不怀好意”(当然,他们可能会把这个“美化”为他们需要关注细节的人才),在JavaScript的领域,这样的问题,数量还不够丰富,而在C/C++的领域,围绕着数组和指针,这样类型的考验,对很多面试者而言,简直就是一种折磨。

好吧,重点在哪里呢?嗯,是的,就是那个出现在花括号前的分号(;)

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

所以,实际上,数组numbers只执行了一次push的操作,所以,numbers的值为:[ 5 ]。

4. 换行也有意义?

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

答案

值是多少,你猜出来了么?

应该是undefined!

怎么,你又没猜对?那我想,你可能是错过了return关键字和[item]表达式之间的这次换行了。

JavaScript不必须要一个分号作为一个语句的结束!

所以,在Prettier之类的工具的帮助下,我们几乎可以马上就让这一代码原形毕露。

答案自然也就呼之欲出了。

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

5. 棘手的关闭

控制台将输出什么?

如果你对于闭包等概念没有很清楚的认识,那么,你猜对这道题目的答案的可能性会很低,或者你会猜,会依次输出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. 讨厌的浮点数

true还是false?

答案

这可能是最没有困扰的一个问题了,我想。大部分人应该都会回答:false,只要他/她接触过编程。

因为是以二进制形式编码,因此像浮点数相加之类的操作,总会产生舍入误差,JavaScript也无法免俗。

在JavaScript下,这个值约略等于:0.30000000000000004,所以,自然的,相等的判断就不会成立。

7. 临时死区和变量提升

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

问题很简单,就是如果在声明这两个变量myVar和myConst前,就访问和使用了这两个变量,会发生什么?

我的经验是,至少60%以上的人,会答错!

答案

这里实际上涉及到了JavaScript作为一种语言,非常独特的两个概念,即:临时死区和变量提升。而这两个概念,又将深深的影响JavaScript变量,在其整个生命周期中的表现。

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

回到我们的问题,就是

myVar一开始会处在变量提升区,因此,其值会返回undefined。而myConst由于其处在临时死区,所以,对该变量的提前访问,会引发一个JavaScript的系统错误。

你GET到这一点了么?

一个简单的总结

还是那句话,我并不认为,这些面试问题,会对你的实际开发能力的提升有多少帮助,在一个开发的团队中,借助于相应的开发规范,实际上会避免很多这样“带有迷惑性”问题的产生。

当然,其中部分的问题,的确可以有效的评估到您,对于JavaScript的语法是否熟悉,但也仅此而已。

在后续的文章中,我也将就这些问题,比如闭包的问题,比如临时死区和变量提升的问题等等,其背后所涉及的相关JavaScript语法现象,做进一步的解读,希望可以给去面试相关工作的人以一定的帮助。

好的,今天就到这里了。

标签: #js语法烂