诚兴裸语很爽,面试工作屡屡遇难。幸好我每天都有一个问题伙伴,点击关注不要偷懒。又到了金九银十的跳槽季。为了让更多的朋友在面试的时候拿到更好的offer,我从上个月开始每天都在我的公众号【前端SomePlay】推送一两个面试题,方便找工作的会每天都有新的收获。这篇文章是小编整理了上期比较经典的一些日常问题。欢迎大家来看看。本文内容首发于公众号【前端玩的一些东西】,关注===学习。类数组面试题什么是类数组,类数组是一个对象,它有一个length属性,其他属性(索引)都是非负整数,没有数组使用的方法。比如我们常用的document.querySelector返回的NodeLists就是一个类数组。这个问题与类数组有关。对于这个问题,请告诉我以下代码的输出。去掉splice后需要区分nodejs、chrome和chromevarobj={'2':3,'3':4,'length':2,'splice':Array.prototype.splice,'push':Array.prototype.push}obj.push(1)obj.push(2)console.log(obj)这道题的答案一共是下面三种情况下的输出,下面会解释下面输出的答案节点{'2':1,'3':2,length:4,splice:[函数:splice],push:[函数:push]}chromebelowOutput[empty×2,1,2,splice:?,push:?]chrome去掉拼接输出{2:1,3:2,length:4,push:?}通过上面输出的内容可以看出,同一个代码在不同情况下的输出是不同,下面是详细的分解。解决方案在回答问题之前,我们先看一下这段代码constarr=newArray(2)//output2[empty*2]console.log(arr.length,arr)arr.push(1)//output3[empty*2,1]console.log(arr.length,arr)可以看到push方法会将数组的长度+1相加,然后把值放在index为length-1的位置,这样如上面的代码,因为在初始化数组的时候,已经指定了数组的长度为2,所以push之后长度变成了3,然后arr[3-1]=1MDN上push方法的解释是:push方法是通用的。当与call()或apply()一起使用时,此方法可应用于类数组对象。push方法使用length属性来确定从哪里开始插入给定值。如果length不能转换为数字,则插入的元素的索引为0,包括length不存在的情况。当length不存在时,将创建它。根据MDN的解释,push既可以用在数组中,也可以用在类数组中。根据上一篇对class数组的解释,可以看到题目中的obj是一个标准的class数组,那么就可以在obj上使用数组的push方法了。再看obj.push(1),因为obj.length=2,所以length+1会变成3。此时,当index值为obj[3-1]=1时,即obj[2]=1,同理obj.push(2)。因为obj中已经有属性(索引)2和3,所以push时会覆盖2和3上面的默认值。所以在nodejs中会输出{'2':1,'3':2,length:4,splice:[Function:splice],push:[Function:push]}但在chrome控制台输出[empty×2,1,2,splice:?,push:?]很奇怪,为什么是这个输出?这一段有个很特别的陷阱,就是chrome控制台怎么判断打印的内容是数组还是其他对象?对于这个,chrome通过判断对象上是否有splice和length两个属性来判断,所以如果去掉splice,就会输出如下内容{2:1,3:2,length:4,push:?}也可以试试下面的代码:console.log({splice:function(){},length:1})console.log({slice:function(){},length:1})逻辑面试题老鼠喝poison小编当年毕业的时候遇到了几道逻辑面试题。这道题是一道逻辑面试题。让我们来看看。一共有16瓶水,只有一瓶水是有毒的。老鼠喝一滴就会在一小时内死亡。请问至少要用多少只老鼠才能在一小时内找出毒水?答案和问题的答案答案是至少需要4只鼠标,你是怎么理解的?我们可以用二进制推理:假设有4只老鼠,分别是A、B、C、D,用二进制表示老鼠喝药的顺序,1表示喝药,0表示不喝药A:1111111100000000B:1111000011110000C:1100110011001100D:1010101010101010那么我们可以这样判断:A、B、C、D都死了,也就是说第一瓶有毒的A、B、C死了,也就是说第二瓶有毒的A、B、D死了,也就意味着第三瓶有毒的A、B死了,也就意味着第四瓶有毒A、B、D死了,也就是说第五瓶有毒。..等等。其实对于这道题,可以用2的n次方来判断。比如有32瓶水,那么就是2的5次方,所以需要5只老鼠。arguments面试题在ES6中,如果我们的函数参数个数不确定,一般使用扩展运算符function(...rest){}来得到一个参数数组rest,但是在ES6之前,我们不能使用扩展运算符,你这个时候需要考虑使用arguments。标题请说明以下程序的输出(chrome输出内容)letobj={arg:18,foo:function(func){func()arguments[0]()}}varage=10functionfn(){console.log(this.age)}obj.foo(fn)Answer这个问题的答案是//首先输出10func()//首先输出undefinedarguments[0]()是不是有点出乎意料?先解释一下第一个,为什么不输出18呢?虽然在foo函数中调用了func(),但它并没有明确指定作用域。这时候会使用默认作用域window,而对于浏览器来说,通过var全局声明的变量会自动挂载到window上,所以varage=10相当于window.age=10,而this.age在第一种func()相当于window.age第二种可能很多人有点疑惑,为什么是undefined,先看下面代码constarr=[function(){console.log(this[1])},'IamZijun']//OutputIamZijunconsole.log(arr[0]())我们通过arr[0]得到函数。此时函数的作用域就是this数组,所以再次调用时,this就是arr,所以this[1]就是数组的第二项。这时候回过头来看arguments,这其实是一个类数组,存放的是函数传入的参数。第一项是传入的函数。像上面的例子,arguments[0]的作用域是arguments,并且arguments上没有age属性,所以undefinedthis指向了问题所在。这个指向的问题一直很扑朔迷离。在箭头函数出现之前,this的指向与代码定义在哪里无关,而取决于执行者是谁。因为,所以很多开发者往往不知道这是谁。以下两个问题与此有关。问题1(铜)请说明以下代码的输出letnum=1;letobj={num:2,add:function(){this.num=3;(function(){console.log(this.num);this.num=4;})();console.log(this.num);},sub:function(){console.log(this.num)}}obj.add();console.log(obj.num);console.log(num);constsub=obj.sub;sub();问题2(Gold)请说明以下代码的输出varnum=10constobj={num:20}obj.fn=(function(num){this.num=num*3num++returnfunction(n){this.nu??m+=nnum++console.log(num)}})(obj.num)varfn=obj.fnfn(5)obj.fn(10)console.log(num,obj.num)输出answer的结果问题一:1,3,3,4,4,你答对了吗?我们看一下代码解析varnum=1;letobj={num:2,add:function(){this.num=3;//这里的直接指向函数是因为我们没有手动指定它的this指向,所以会指向window(function(){//所有this.num等于window.numconsole.log(this.num);this.num=4;})();console.log(this.num);},子:函数(){console.log(this.num)}}//下面会逐行解释打印的内容/***当通过obj.add调用add函数时,函数的this指向obj,此时的首先this.num=3*相当于obj.num=3,但是里面的立即指向函数还是window,*所以立即执行函数中的console.log(this.num)输出1,window.num=4*函数立即执行后,然后输出`this.num`,此时`this`为`obj`,所以输出3*/obj.add()//输出13//通过执行上面的`obj.add`,obj.name变成了3console.log(obj.num)//Output3//这个num是window.numconsole.log(num)//Output4//如果obj.sub被赋值给一个新的变量,那么这个函数的作用域就会变成新变量的作用域constsub=obj.sub//作用域变成windowwindow.numis4sub()//输出4第二题的输出是:22236530,你答对了吗?我们来分析一下varnum=10constobj={num:20}obj.fn=(function(num){this.num=num*3num++returnfunction(n){this.num+=nnum++console.log(num)}})(obj.num)varfn=obj.fnfn(5)obj.fn(10)console.log(num,obj.num)我们将上面的代码分成以下几步进行分析。这三行代码是一个赋值操作。我们知道赋值操作是从右向左的,=号右边是立即执行函数,所以立即执行函数会先执行。立即执行功能不会手动指定这一点。此时this=window,立即函数的参数num是传入的obj.num,所以num参数默认值为20。第四行相当于window.num=20*3。第五行给传入的参数加一,所以num=20+1第六行返回一个函数,而这个函数就是obj.fn的值,但是因为返回函数引用了立即执行函数中的num,所以此时形成了一个闭包obj.fn=function(n){this.num+=n//这个num就是立即执行函数console.log(num)中的num}varfn=obj.fn,把obj.fn赋给一个新的变量,这个变量的作用域就是window在调用fn(5)此时在第二步中,window.num的值已经变成了60,而由于此时fn的this为window,所以this.num+=n等价于window.num+=n,即window.num=65num++,因为闭包,第三步num为21,所以这一步num变成22,同时输出22,然后obj.fn(10)。此时fn的this为obj,obj.num默认值为20,这个.num+=n相当于obj.num+=10同第七步,num+1输出23console。log(num,obj.num)等同于console.log(window.num,obj.num),从上面几步,window.num=65,obj.num=30。扩展题,如果把上面两道题的var改成let,会输出什么?数据类型转换问题虽然在日常开发中,我们用到的隐式类型转换比较少(不一定),但这仍然是面试中经常被问到的问题,掌握它还是很有必要的。我们来看看这个话题。题目(王炸/bronze,我也不知道)说说下面的代码输出什么console.log([]+[])console.log({}+[])console.log([]==![])console.log(true+false)answer让我们来看看答案。第一行代码//output""anemptystringconsole.log([]+[])这行代码输出一个空字符串"",包装类型计算时,会先调用valueOf方法。如果valueOf返回包类型,则调用toString方法//或者数组constval=[].valueOf()//数组toString默认将数组项用逗号",,"分隔,如[1,2,3].toSting变成"1,2,3",空数组toString是一个空字符串constval1=val.toString()//val1是一个空字符串所以上面的代码相当于console.log(""+"")第二行代码//输出"[objectObject]"console.log({}+[])同第一题,对象{}隐式转换成为[objectObject],然后在第三行代码中加上""//输出trueconsole.log([]==![])对于===,两者的值会严格比较,但是对于==就不一样了.比如null==undefined,如果一个非数字和一个数字比较,它会被转换成一个数字。如果比较的两侧之一是布尔值,那么布尔值将首先转换为数字。所以对于上面的代码,看下面一步一步的分析//Thisoutputsfalseconsole.log(![])//应用上面的第三项将false转换为一个值//Thisoutputs0console.log(Number(false))//包装类型和基本类型==第一个包装类型通过valueOftoString转换为基本类型//输出""console.log([].toString())//应用第2条,将一个空字符串转为一个值,//输出0console.log(Number(""))//所以第四行代码在console.log(0==0)//Output1console.log(true+false)添加两个基本类型,如果其中一个是字符,则将另一个转换为字符并相加,否则将类型转换为Number,然后相加,Number(true)为1,Number(false)为0,所以结果为1。总结面试。建造火箭,拧螺丝工作。虽然我只是想拧螺丝,但我需要通过造火箭找一份拧螺丝的工作。每天一题,每天都有新面试题,请关注公众号【前端玩的一些东西】,我拉你进前端技术交流群,一题一答日子等你一起来回答。结语不要耗尽你的灵感和想象力;不要成为模型的奴隶。-文森特-梵高
