当裸辞遇到了面试难,你需要了解一下这些面试题

卡尔 等级 363 0 0

乘兴裸辞心甚爽,面试工作屡遭难。 幸得每日一题伴,点击关注莫偷懒。

又要到金九银十的跳槽季了,为了让更多的小伙伴可以在面试的时候取的更好的offer,所以自上月起我每天都会在自己的公众号【前端有的玩】里面推送一到两道面试题,俗称每日一题(每日一坑)。方便找工作的小伙伴每日都会有新的收获。本文就是小编将前期的一些比较经典的每日一题进行了梳理,欢迎大家一起来看看。本文内容首发于公众号【前端有的玩】,关注 === 学会。

一道类数组相关面试题

什么是类数组,类数组就是 拥有length属性,且其他属性(索引)为非负整数的对象,且不具备数组所用于的方法。比如我们常用的document.querySelectorAll返回的NodeLists就是一个类数组。这道题就是和类数组相关的内容.

题目

请说出以下代码输出的内容,需要区分nodejs,chrome以及chrome去掉splice之后的输出内容

var obj = {
    '2': 3,
    '3': 4,
    'length': 2,
    'splice': Array.prototype.splice,
    'push': Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj) 

答案

这道题一共问了三种情况下面的输出,下面依次说明答案

  1. node下面输出

    { '2': 1,
      '3': 2,
      length: 4,
      splice: [Function: splice],
      push: [Function: push] } 
  2. chrome下面输出

    [empty × 2, 1, 2, splice: ƒ, push: ƒ] 
  3. chrome去掉splice下面输出

    {2: 1, 3: 2, length: 4, push: ƒ} 

通过上面输出的内容,可以看出相同的代码,不同情况输出的内容是有所不同的,下面进行详细分解。

题解

在解答题目之前,我们再看看这段代码

const arr = new Array(2)
// 输出  2 [empty * 2]
console.log(arr.length, arr)
arr.push(1)
// 输出  3 [empty * 2, 1]
console.log(arr.length, arr) 

可以看到push方法会将数组的length + 1, 然后将值放在索引为length - 1的位置,比如上面的代码,因为在初始化数组的时候,已经将数组长度指定为了2, 所以在push之后length就变成了3,然后arr[3 - 1] = 1

MDN上面对push的方法的解释是:

push 方法具有通用性。该方法和 call()apply() 一起使用时,可应用在类似数组的对象上。push 方法根据 length 属性来决定从哪里开始插入给定的值。如果 length 不能被转成一个数值,则插入的元素索引为 0,包括 length 不存在时。当 length 不存在时,将会创建它。

根据MDN解释,push既可以使用到数组中,也可以使用到类数组中。而根据前文中对类数组的解释,可以看到题目中的obj就是一个标准的类数组,那就可以在obj上面使用数组的push方法。

再看obj.push(1), 因为obj.length = 2, 所以会将length + 1就变成了3, 这时候 索引值时obj[3 - 1] = 1obj[2] = 1, 同理 obj.push(2) 也一样的。因为在obj中已经有了属性(索引)23,所以在push的时候会覆盖掉23上面的默认值。

所以在nodejs中就会输出

{ '2': 1,
  '3': 2,
  length: 4,
  splice: [Function: splice],
  push: [Function: push] } 

但是在chrome控制台中输出

[empty × 2, 1, 2, splice: ƒ, push: ƒ] 

很奇怪,为什么会输出这样呢?这一块有一个很特殊的陷阱,就是chrome控制台是如何判断打印的内容是数组还是其他对象呢?对于这个,chrome就是通过判断对象上面是否有splicelength这两个属性来判断的,所以如果你将splice去掉之后,就会输出以下内容

{2: 1, 3: 2, length: 4, push: ƒ} 

你也可以试试下面的代码:

console.log({splice:function(){},length:1})
console.log({slice:function(){},length:1}) 

逻辑面试题之小鼠喝毒药

小编当年毕业的时候面试就遇到过好几次逻辑类的面试题,这道题就是一道逻辑类的面试题,一起来看看。

题目

有16瓶水,其中只有一瓶水有毒,小白鼠喝一滴之后一小时会死,请问最少用多少只小白鼠,在1小时的时间一定可以找出有毒的水?

答案与题解

答案是至少需要4只小鼠,怎么理解呢?我们可以用二进制去推理一下:

假设有4只小鼠,分别是甲乙丙丁,使用二进制来表示小鼠喝药的顺序,1代表喝药,0代表不喝药

甲: 1111 1111 0000 0000

乙: 1111 0000 1111 0000

丙: 1100 1100 1100 1100

丁: 1010 1010 1010 1010

那么我们就可以这样去判断:

  1. 甲乙丙丁都死了,说明第一瓶有毒
  2. 甲乙丙死了,说明第二瓶有毒
  3. 甲乙丁死了,说明第三瓶有毒
  4. 甲乙死了,说明第四瓶有毒
  5. 甲丙丁死了,说明第五瓶有毒
  6. 。。。 依次类推

其实对于这道题,可以使用2n次方来判断,比如有32瓶水,那么就是25次方,所以就需要5只小鼠。

arguments 面试题

ES6中,我们如果一个函数参数个数不确定,我们一般会使用扩展运算符即function(...rest){},得到一个参数数组rest,但是在ES6之前,我们是不能使用扩展运算符的,这时候就需要考虑使用arguments

题目

请说出以下程序输出的内容(chrome输出内容)

let obj = {
  age: 18,
  foo: function(func) {
    func()
    arguments[0]()
  }
}

var age = 10
function fn() {
  console.log(this.age)
}

obj.foo(fn) 

答案

本题的答案是:

// 第一个输出 10
func()
// 第一个输出 undefined
arguments[0]() 

有点出乎意料了吗?

先来解释一下第一个,为什么不是输出18呢,虽然func()是在foo函数里面调用的,但是并没有显式指明作用域,这时候会使用默认作用域window,而对于浏览器来说,在全局通过var声明的变量会自动挂载到window上面,所以var age = 10相当于window.age = 10, 而第一个func()里面的this.age相当于window.age

第二个可能许多人有点蒙,为啥是undefined,先看一下下面的代码

const arr = [function() {console.log(this[1])}, '我是子君']
// 输出 我是子君
console.log(arr[0]()) 

我们通过arr[0]获取到函数,这时候函数的作用域就是这个数组,所以再调用的时候,this就是arr, 所以this[1]就是数组第二项。

这时候回过头来看arguments,这个其实是一个类数组,里面存的是函数传入的参数,第一项就是传入的函数,和上面例子一样,arguments[0]的作用域就是arguments,而arguments上面并没有age属性,所以是undefined

this指向问题

this指向问题一直是比较混乱的,在箭头函数出现之前,this的指向与代码在哪里定义并没有关系,而是取决于是被谁执行的,正因为此,所以许多开发人员经常会搞不清楚this到底是谁。下面的两道题都是和this指向相关的问题。

题目一(青铜)

请说出以下代码输出的内容

var num = 1;
let obj = {
    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);
const sub = obj.sub;
sub(); 

题目二(黄金)

请说出以下代码输出的内容

var num = 10
const obj = {num: 20}
obj.fn = (function (num) {
  this.num = num * 3
  num++
  return function (n) {
    this.num += n
    num++
    console.log(num)
  }
})(obj.num)
var fn = obj.fn
fn(5)
obj.fn(10)
console.log(num, obj.num) 

答案

题目一

输出结果: 1,3,3,4,4, 你答对了吗?下面我们来看看代码解析

var num = 1;
let obj = {
    num: 2,
    add: function() {
        this.num = 3;
          // 这里的立即指向函数,因为我们没有手动去指定它的this指向,所以都会指向window
        (function() {
            // 所有这个 this.num 就等于 window.num
            console.log(this.num);
            this.num = 4;
        })();
        console.log(this.num);
    },
    sub: function() {
        console.log(this.num)
    }
}
// 下面逐行说明打印的内容

/**
 * 在通过obj.add 调用add 函数时,函数的this指向的是obj,这时候第一个this.num=3
 * 相当于 obj.num = 3 但是里面的立即指向函数this依然是window,
 * 所以 立即执行函数里面console.log(this.num)输出1,同时 window.num = 4
 *立即执行函数之后,再输出`this.num`,这时候`this`是`obj`,所以输出3
 */
obj.add() // 输出 1 3

// 通过上面`obj.add`的执行,obj.name 已经变成了3
console.log(obj.num) // 输出3
// 这个num是 window.num
console.log(num) // 输出4
// 如果将obj.sub 赋值给一个新的变量,那么这个函数的作用域将会变成新变量的作用域
const sub = obj.sub
// 作用域变成了window window.num 是 4
sub() // 输出4 
题目二

输出结果为: 22 23 65 30, 你答对了吗? 下面我们解析一下

var num = 10
const obj = {num: 20}
obj.fn = (function (num) {
  this.num = num * 3
  num++
  return function (n) {
    this.num += n
    num++
    console.log(num)
  }
})(obj.num)
var fn = obj.fn
fn(5)
obj.fn(10)
console.log(num, obj.num) 

我们把上面的代码分为以下几步进行分析

  1. 先看第三行代码,是一个赋值操作,我们知道赋值操作是从右向左的,而=号右边是一个立即执行函数,所以会优先执行立即执行函数,立即执行函数没有手动指定this,这时候this = window,而立即函数的参数num是传进来的obj.num,所以num参数默认值是 20

  2. 第四行相当于window.num = 20 * 3

  3. 第五行为传入的参数加一,所以 num = 20 + 1

  4. 第六行return了一个函数,而这个函数就是obj.fn的值, 但是因为return的函数引用了立即执行函数里面的num,所以形成了闭包。这时候

    obj.fn = function(n) {
      this.num += n
      // 这个num是立即执行函数里面的num
      num++
      console.log(num)
    } 
  5. var fn = obj.fn, 将obj.fn赋值给新的变量,而这个变量的作用域是window

  6. 在调用fn(5)的时候, 在第二步,window.num的值已经变成了60, 然后因为这时候fnthiswindow, this.num += n相当于window.num += n, 即window.num = 65

  7. num++, 因为闭包的原因,第三步num21,所以这一步 num变成了22, 同时输出22

  8. 然后obj.fn(10),这时候fnthisobj,obj.num默认值是20, this.num += n相当于 obj.num += 10

  9. 和第七步一样, num + 1 输出 23

  10. console.log(num, obj.num)相当于 console.log(window.num, obj.num),从上面几步可知, window.num = 65, obj.num = 30

扩展题

如果将上面两道题的 var改成 let, 又会输出什么结果呢?

数据类型转换问题

虽然在日常开发中,我们隐氏类型转换用的比较少(不一定),但是这个还是面试常问问题,掌握还是要掌握的,一起来看看这道题目吧.

题目(王炸/青铜,我也不知道)

请说出以下代码输出的内容

console.log([] + [])
console.log({} + [])
console.log([] == ![])
console.log(true + false) 

答案

一起来看看答案吧

  1. 第一行代码
// 输出 "" 空字符串
console.log([] + []) 

这行代码输出的是空字符串"", 包装类型在运算的时候,会先调用valueOf方法,如果valueOf返回的还是包装类型,那么再调用toString方法

// 还是 数组
const val = [].valueOf()
// 数组 toString 默认会将数组各项使用逗号 "," 隔开, 比如 [1,2,3].toSting 变成了"1,2,3",空数组 toString 就是空字符串
const val1 = val.toString() // val1 是空字符串 

所以上面的代码相当于

console.log("" + "") 
  1. 第二行代码

    // 输出 "[object Object]"
    console.log({} + []) 

    和第一题道理一样,对象 {}隐氏转换成了[object Object],然后与""相加

  2. 第三行代码

    // 输出 true
    console.log([] == ![]) 

    对于===, 会严格比较两者的值,但是对于==就不一样了

    1. 比如 null == undefined
    2. 如果非numbernumber比较,会将其转换为number
    3. 如果比较的双方中由一方是boolean,那么会先将boolean转换为number

    所以对于上面的代码,看下面一步一步分析

    // 这个输出 false
    console.log(![])
    // 套用上面第三条 将 false 转换为 数值
    // 这个输出 0
    console.log(Number(false))
    // 包装类型与 基本类型 == 先将包装类型通过 valueOf toString 转换为基本类型 
    // 输出 ""
    console.log([].toString())
    // 套用第2条, 将空字符串转换为数值、
    // 输出 0
    console.log(Number(""))
    // 所以
    console.log(0 == 0) 
  3. 第四行代码

    // 输出 1
    console.log(true + false) 

    两个基本类型相加,如果其中一方是字符,则将其他的转换为字符相加,否则将类型转换为Number,然后相加, Number(true)1, Number(false)0, 所以结果是 1

总结

面试造火箭,工作拧螺丝。虽然我只想拧螺丝,但是我却需要通过造火箭来找到拧螺丝的工作,每日一题,每天都有新的面试题目,欢迎关注公众号【前端有的玩】,拉你进入前端技术交流群,每日一题等着你来一起答题。

结语

不要吹灭你的灵感和你的想象力; 不要成为你的模型的奴隶。 ——文森特・梵高

本文转自 https://juejin.cn/post/6866920515420815374,如有侵权,请联系删除。

收藏
评论区

相关推荐

当遇到跨域开发时, 我们如何处理好前后端配置和请求库封装(koa/axios版)
我们知道很多大型项目都或多或少的采用跨域的模式开发, 以达到服务和资源的解耦和高效利用. 在大前端盛行的今天更为如此, 前端工程师可以通过nodejs或者Nginx轻松搭建起web服务器.这个时候我们只需要请求后端服务器的接口即可实现系统的业务功能开发.这个过程中会涉及到web页面向API服务器的跨域访问(由于受到浏览器的同源策略,但是业界已有很多解决方案,
Gartner:敏捷开发的10大指导原则
据Gartner的资料表明,一众CIO现在有压力,需要支持快速发展的数字业务发展,而同时又遇上传统项目和开发方法不能与时俱进的难题。企业现在大量采用敏捷开发,以加快项目进度及更好地显示其价值。 Gartner应用架构、开发和整合峰会下个月在悉尼召开。Gartner公司研究总监Nathan Wilson在会议前夕表示,敏捷方法如果使用得当,是有能力改变IT业
后台更新数据方案
当你遇到一些让你大吃一惊的解决方案的时候你不要惊讶,要学会低头去面试它,解决它。最近公司项目要做个人脸识别,类似于门禁卡之类的。本来这也没什么,因为我接到任务后第一反应是这样的逻辑:设备采集图片 设备识别图片是否是人脸 是人脸 提交服务器进行身份识别 服务器返回人物身份信息我觉得这样的逻辑就是有点耗时。然后根据公司需求是要做百度人脸的
聊聊前端面试
前言面试造飞机,入职拧螺丝。裸面是不可能裸面的,这辈子都不可能再裸面的了!因为它会严重打击你的自信心,面试官能把你虐到怀疑人生。作为一个工作了将近 3 年前端er,来简单聊聊自己面试所做的一些准备。PS. 最终拿到了虎牙直播、有赞、金蝶、晓教育前端小组长、明源云的 Offer,经过对比,目前在深信服,哈哈,意不意外,惊不惊喜???热身篇 确
当裸辞遇到了面试难,你需要了解一下这些面试题
乘兴裸辞心甚爽,面试工作屡遭难。 幸得每日一题伴,点击关注莫偷懒。又要到金九银十的跳槽季了,为了让更多的小伙伴可以在面试的时候取的更好的offer,所以自上月起我每天都会在自己的公众号【前端有的玩】里面推送一到两道面试题,俗称每日一题(每日一坑)。方便找工作的小伙伴每日都会有新的收获。本文就是小编将前期的一些比较经典的每日一题进行了梳理,欢迎大家一起
Android研发面试大厂,知识点整理
前言不知道你们多长时间没有参加过面试了,最近这段时间的面试,真的是一个比一个严格!我昨天参加了一线大厂的技术面,当场给我吓die了,没想到这么难!如果你不信,你也来die die: 画出 Android 的大体架构图 描述请点击 Android Studio 的 build 按钮后发生了什么,大体说清一个应用程序安装到手机上时发生了什
2021前端技术面试必备Vue:(一)基础快速学习篇
由于疫情的影响,相信很多小伙伴都在家里待着。中小公司由于运营困难会出现裁员, 我们也面临着 '失业',你是否感到了焦虑.最近做了个调研: '现在的你找到工作了吗 ?<br/1.大部分的回复: 求职平台都是 ‘已回复’,然后没有下文,你遇到了吗?<br/2.各个公司对技术的要求增高<br/3.有人说开始搞副业<br/ 在我来看,这一年已经过去了四分
Vue进阶(幺陆柒):Vue项目调试技能
前言在Vue项目开发过程中,当你遇到应用逻辑出现错误,但又无法准确定位的时候,知晓Vue项目调试技巧至关重要。同后台项目开发一样,可以在JS实现的应用逻辑中设置断点,并进行单步、进入方法内、跳出方法等调试,从而准确定位问题根源
零基础成功转行python工程师,从月薪4K到现在月入过W!
本人文科生,回顾自己Python的学习经历,有一些学习心得和避坑经验分享给大家,让大家在学习 Python 的过程中少走一些弯路!减少遇到不必要的学习困难!我学习python的目的挺俗的,就是为了更高的职位和薪水,当时因为计算机基础不是很好,可以说特别的困难了,看了一些网上的教程学习,可以说是拆东墙补西墙的做法,差点就...而且总是记不住一些基础语法,刚开始
自动化办公 | (升级版)批量将Excel中的url链接转成图片②
大家好,我是小五🚀前面我们使用,结果读者后来跟我反馈又遇到了一些问题。于是乎,干脆对前几天的代码升级一波。需求简介具体原始数据和期望结果如下图所示:但这位读者朋友又遇到了一个问题👇 解决当url为空时代码停止运行的问题 将图片保存到新增文件夹,大概有1.4W张图片,后续删图片有难度 第一个问题呢,只需加个判断语句就可以。至于将图片保存到
分享一位同学的阿里、百度前端面经
【第一部分 面试前的准备】从决定找工作开始,我其实经历过一系列思想斗争,最开始想的是,等自己完全准备充分之后,再开始投简历面试。然而,由于惰性,我发现自己很难判断什么时候是完全准备好的时候。这次换工作的第一次面试,当时的心态就是报着学习的态度,总要迈出第一步,也许当你放低了自己的预期,实际面试过程中可能也就不会那么紧张和不自然了,我当时报的期望就是通过面试查
开放API接口签名验证,让你的接口从此不再裸奔
接口安全问题 请求身份是否合法? 请求参数是否被篡改? 请求是否唯一? AccessKey&SecretKey (开放平台) 请求身份为开发者分配AccessKey(开发者标识,确保唯一)和SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)。 防止篡改参数签名1. 按照请求参数名的字母升序排列非空请求参数(包含AccessK
canvas图像识取技术以及智能化思考
笔者最近一直在研究 前端可视化 和 搭建化 的技术, 最近也遇到一个非常有意思的课题, 就是基于设计稿自动提取图片信息, 来智能化出码. 当然本文并不会介绍很多晦涩难懂的技术概念, 我会从几个实际应用场景出发, 介绍如何通过canvas图像识取技术来实现一些有意思的功能. 最后会总结一些对智能化的思考以及对低代码方向的规划, 希望能对各位有所启发. canv
Python爬虫 | Selenium爬取当当畅销图书排行
01 前言 上篇文章我们爬取了,心情相当愉悦,今天这篇文章我们使用Selenium来爬取当当网的畅销图书排行。正所谓书中自有黄金屋,书中自有颜如玉,我们通过读书学习来提高自身的才华,自然能有荣华富贵,也自然少不了漂亮小姐姐。 02 准备工作 在爬取数据前,我们需要安装Selenium库以及Chrome浏览器,并配置好Chro
Pandas专家总结:指定样式保存excel数据的 “N种” 姿势!
作者:小小明 简介:Pandas数据处理专家,10余年编码经验,至今已帮助过百名以上数据从业人员解决工作实际遇到的问题,其中数据处理和办公自动化问题涉及的行业包括会计、审计、HR、气象工作人员、教师、律师、运营,以及各行业的数据分析师和专做数据分析案例的公众号号主。 若你在数据处理的问题上遇到什么困难,欢迎与我交流。目录 准备数据