当前位置: 欣欣网 > 码农

2年经验,面试字节跳动,感觉也不是很难

2024-04-01码农

模拟面试、简历指导、入职指导、项目指导、答疑解惑 可私信找我~已帮助100+名同学完成改造!

前言

大家好,我是林三心,用最通俗易懂的话讲最难的知识点是我的座右铭,基础是进阶的前提是我的初心~

题目

一面

  • 1、['10', '10', '10', '10', '10'].map(parseInt) 的输出值是什么?

  • 2、你们现在的技术栈是什么?为什么要使用ts?

  • 3、setTimeout的执行过程(事件循环,同步、异步)?

  • 4、对Promise的理解,与async、await的区别,async、await是怎么实现的?

  • 5、解释 requestAnimationFrame/requestIdleCallback,分别有什么用?

  • 6、react性能优化?

  • 7、说说对flex的理解?

  • 8、回流、重绘是什么?如何减少回流和重绘?

  • 10、怎么寻找react页面卡顿的原因?

  • 11、编程题:实现一个对象的 flatten 方法,如下:

  • const obj = { a: { b1, c2, d: { e5 } }, b: [13, {a2b3}], c3 }

    flatten(obj){} 结果返回如下:

    // { // 'a.b': 1, // 'a.c': 2, // 'a.d.e': 5, // 'b[0]': 1, // 'b[1]': 3, // 'b[2].a': 2, // 'b[2].b': 3 // c: 3 // }

    二面

  • 1、说说对web worker的理解

  • 2、service worker和强缓存相比,有哪些优势?

  • 3、说说对堆栈溢出的理解

  • 4、position中的sticky是什么,还有哪些其他的?

  • 5、ts中,any和unknown分别是什么意思?泛型怎么使用?

  • 6、bind有什么用?连续多个bind,最后this指向是什么?

  • 7、webpack的plugin怎么实现?

  • 8、编程题:现已知一个字符串是由正整数和加减乘除四个运算符(+ - * /)组成。例如存在字符串 const str = '11+2-3 4+5/2 4+10/5',现在需要将高优先级运算,用小括号包裹起来,例如结果为 '11+2-(3 4)+(5/2 4)+(10/5)'。注意可能会出现连续的乘除运算,需要包裹到一起。请用 javascript 实现这一过程

  • 三面

  • 1、手写体:使用TypeScript 实现一个 get 函数来获取它的属性值

  • const data = { name'tom'age18address'xxx' }

  • 2、ts中的 any 、 unknown 的区别

  • 3、有用过ts中的 keyof 吗?

  • 4、for in/for of的区别?

  • 5、Promise值穿透?

  • 解答

    一面

    1、['10', '10', '10', '10', '10'].map(parseInt) 的输出值是什么?

    可转化为:

    ['10''10''10''10''10'].map((num, index) =>parseInt(num, index))
    // [10, NaN, 2, 3, 4]
    '10'0 -> 10: 进制为0,则默认10进制
    '10'1 -> NaN: 1进制不存在
    '10'2 -> 2: 2 * 1 + 2 * 0
    '10'3 -> 3: 3 * 1 + 3 * 0
    '10'4 -> 4: 4 * 1 + 4 * 0

    2、你们现在的技术栈是什么?为什么要使用ts?

    typescript JavaScript 的超集,它本质其实是是在 JavaScript 上添加了 可选静态类型 基于类的面向对象编程

    typescript 的特点

  • 可以在编译期间发现并纠正错误

  • 提高可维护性

  • 提高协同开发的效率

  • 支持强类型、接口、泛型、模块

  • 3、setTimeout的执行过程(事件循环,同步、异步)?

    事件循环

  • 1、执行同步代码

  • 2、 1 中生成的 微任务 先执行

  • 3、 1 中生产的 宏任务 再执行 同步

  • 简单来说就是:排队。代码有前后顺序,必须按照顺序去执行 异步

    异步任务可以不阻塞后面的代码执行,而是可以同时进行,并且执行完后会有一个异步的回调。

    想起一个故事可以很好的解释 同步 异步

  • 同步:你打电话去书店借书,老板接电话时让你等着,他去找书,你只能守着电话干等着

  • 异步:你打电话去书店借书,老板接电话后说等他找到书再打回给你,然后挂电话了,这段找书的时间你可以自由活动

  • 4、对Promise的理解,与async、await的区别,async、await是怎么实现的?

    Promise的理解

    顾名思义, Promise 就是 承诺 的意思,表现在了Promise的状态一旦改变则不会再变了,如果状态为 fulfilled 则执行 then ,如果状态为 rejected 则执行 catch ,Promise 也支持 链式调用 。我觉得Promise最大的用处就是 解决了回调地狱,提高了代码的可读性 。常用的方法有 resolve、reject、then、catch、race、all、allSettled、any、finally

    async await async/await 的作用是 用同步的方式执行异步的操作 ,它的实现原理,我个人理解就是利用了 Promise 的不断嵌套,再加上 generator函数 的步骤控制,实现了按顺序执行异步操作的效果

    补充:async函数返回的是一个Promise

    5、解释 requestAnimationFrame/requestIdleCallback,分别有什么用?

  • requestAnimationFrame:

  • 一般间隔是 16ms ,因为大部分电脑都是 每秒60帧 ,所以 1000 / 60 ≈ 16ms

  • 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中完成,且时间间隔紧紧跟随浏览器的刷新频率

  • 如果有隐藏或不可见的元素,将不会进行重绘或回流,减少了cpu、gpu的内存使用量

  • 如需取消则使用 cancelAnimationFrame

  • requestIdleCallback:我的理解就是找浏览器空闲时间去执行传入的回调,具体也没在项目中使用过

  • 6、react性能优化?

    7、说说对flex的理解?

    弹性布局 ,设置了 display: flex 的盒子为 弹性盒子 ,子元素会自动变成 弹性项目 ,盒子有一根主轴,默认是水平,并且有一个交叉轴(跟主轴垂直)。

    弹性盒子的样式:

  • flex-direction:定义主轴方向

  • flex-wrap:是否允许换行

  • flex-flow:flex-direction 和 flex-wrap的简写

  • justify-content:主轴方向上的对齐方式

  • align-items:交叉轴方向的对齐方式

  • align-content:多根轴线的对齐方式

  • 弹性项目的样式:

  • order:定义项目的排列顺序,数值越小排列越靠前,默认0

  • flex-grow:定义项目的放大比例,默认为 0

  • flex-shrink:定义项目的缩小比例,默认为1

  • flex-basis:定义了在分配多余空间之前,项目占据的主轴空间,默认auto

  • flex:flex-grow、flex-shrink、flex-basis的简写

  • align-self:允许单个项目设置不同的交叉轴对齐方式

  • 8、回流、重绘是什么?如何减少回流和重绘?

    重绘回流

  • 回流:尺寸、布局改变时,引起页面重新构建

  • 重绘:元素外观、风格改变时,不影响布局,则为重绘

  • 区别:回流一定引起重绘,重绘不一定引起回流

  • 浏览器帮忙:浏览器维护一个队列,把所有引起回流、重绘的操作放入这个队列,等队列到了一定数量或者到了一定的时间间隔,浏览器就会清空队列,进行批量处理。

  • 避免重绘、回流

  • 1、批量修改DOM或者样式

  • 2、复杂动画使用绝对定位让它脱离文档流,不然会影响父元素或后续元素的频繁回流

  • 3、GPU加速:transform、opacity、filters、will-change等样式

  • 9、判断一个对象是数组的方法?

  • Object.prototype.toString.call(xxx)

  • Array.isArray(xxx)

  • xxx instaceOf Array

  • 10、怎么寻找react页面卡顿的原因?

    11、编程题:实现一个对象的 flatten 方法,如下:

    const obj = { a: { b1, c2, d: { e5 } }, b: [13, {a2b3}], c3 }

    flatten(obj){} 结果返回如下:

    // { // 'a.b': 1, // 'a.c': 2, // 'a.d.e': 5, // 'b[0]': 1, // 'b[1]': 3, // 'b[2].a': 2, // 'b[2].b': 3 // c: 3 // }

    解题

    const isObject = (target) => {
    returntypeof target === 'object' && target !== null
    }
    const flatten = (obj) => {
    if (!isObject) return
    const res = {}
    const dfs = (cur, prefix) => {
    if (isObject(cur)) {
    if (Array.isArray(cur)) {
    cur.forEach((item, index) => dfs(item, `${prefix}[${index}]`))
    else {
    for(let key in cur) {
    dfs(cur[key], `${prefix}${prefix ? '.' : ''}${key}`)
    }
    }
    else {
    res[prefix] = cur
    }
    }
    dfs(obj, '')
    return res
    }

    二面

    1、说说对web worker的理解

  • 1、开启一个子线程,并在此子线程进行一些大数据处理或者耗时的操作

  • 2、使用 postMessage onmessage ,实现主线程和子线程之间的通信

  • 3、使用 onerror 监听子线程挂了没

  • 4、 web worker 并没有改变JavaScript单线程的事实

  • 2、service worker和强缓存相比,有哪些优势?

    service缓存没用过。。

    3、说说对堆栈溢出的理解?

    常见的情况发生在 大数量递归 死循环 时,就会造成 栈溢出 ,因为每次执行代码都需要分配一定空间的内存,以上两种情况都会使执行空间超出最大限度,从而报错

    4、position中的sticky是什么,还有哪些其他的?

  • static:默认

  • relative:相对定位,相对于自身定位

  • absolute:绝对定位,相对于非static的第一个祖宗元素定位

  • fixed:相对于浏览器窗口进行定位

  • inherit:规定应该从父元素继承 position 属性的值

  • sticky:吸顶定位

  • 5、ts中,any和unknown分别是什么意思?泛型怎么使用?

  • any:变量如果是 any 类型,绕过所有类型检查,直接可使用

  • unknown:变量如果是 unknow 类型,需要判断完是什么类型之后才能使用

  • 6、bind有什么用?连续多个bind,最后this指向是什么?

    bind 的作用是改变函数执行的指向,且不会立即执行,而是返回一个新的函数,可以自主调用这个函数的执行(此函数不可当做构造函数)

    连续多个bind之后this指向始终指向第一个

    7、webpack的plugin怎么实现?

    一个plugin就是一个类,类里有一个 apply方法 ,每次打包时都会调用这个apply,而这个apply方法接受一个参数对象,其中有一个 plugin 方法,此方法中有许多 钩子函数 ,且可以决定静态文件的生成,修改等等

    8、编程题:

    现已知一个字符串是由正整数和加减乘除四个运算符(+ - * /)组成。例如存在字符串 const str = '11+2-3 4+5/2 4+10/5',现在需要将高优先级运算,用小括号包裹起来,例如结果为 '11+2-(3 4)+(5/2 4)+(10/5)'。注意可能会出现连续的乘除运算,需要包裹到一起。请用 javascript 实现这一过程

    解答 我比较菜,用的方法也是临时想出来的,没有优化,大家将就着看吧:

    const checkType = (str) => {
    if (['*''/'].includes(str)) return'high'
    if (['+''-'].includes(str)) return'low'
    return'number'
    }
    const addBrackets = (formula) => {
    const strs = formula.split('')
    let i = 0, j = 1, high = false, res = []
    while(j < strs.length) {
    const jType = checkType(strs[j])
    if (jType === 'low' && !high) {
    i = ++j
    j++
    }elseif (jType === 'low' && high) {
    res.push(j++)
    i = j++
    high = false
    }elseif (jType === 'high') {
    j++
    !high && res.push(i)
    high = true
    }else {
    j++
    }
    }
    if (high) res.push(strs.length)
    let add = 0
    for(let i = 0; i < res.length; i++) {
    const index = res[i]
    strs.splice(index + add, 0, add % 2 ? ')' : '(')
    add++
    }
    return strs.join('')
    }

    三面

    1、手写体:使用TypeScript 实现一个 get 函数来获取它的属性值

    const data = { name'tom'age18address'xxx' }

    解答:

    constget = <T extends object, K extends keyof T>(obj: T, key: K): T[K] => {
    return obj[key]
    }

    2、ts中的 any 、 unknown 的区别?

  • any:变量如果是 any 类型,绕过所有类型检查,直接可使用

  • unknown:变量如果是 unknow 类型,需要判断完是什么类型之后才能使用

  • 3、有用过ts中的 keyof 吗?

    将一个interface的所有key,汇聚成一个联合类型,可以用来对传入key的限制,比如:

    interface Target {
    name: string,
    age: number
    }
    const fn = (obj: Target, key: keyof Target) => {}
    const obj: Target = { name'sunshine'age18 }
    fn(obj, name) // 成功
    fn(obj, age) // 成功
    fn(obj, height) // 报错

    4、for in/for of的区别?

  • for in:遍历对象的key或者数组的索引

  • for of:遍历可迭代对象的值,如数组、Set

  • 5、Promise值穿透

    then或catch没有传入函数的话,会发生值穿透,原理是Promise内部检测如果传入的是非函数,则会拿上一次的结果包装成一个返回Promise的函数,达到穿透效果

    例如:

    Promise.resolve('foo')
    .then(Promise.resolve('bar'))
    .then(function(result){
    console.log(result) // foo
    })

    但是如果传入的是函数的话:

    Promise.resolve('foo')
    .then(() =>Promise.resolve('bar'))
    .then(function(result){
    console.log(result) // bar
    })

    结语

    我是林三心

  • 一个待过 小型toG型外包公司、大型外包公司、小公司、潜力型创业公司、大公司 的作死型前端选手;

  • 一个偏前端的全干工程师;

  • 一个不正经的掘金作者;

  • 逗比的B站up主;

  • 不帅的小红书博主;

  • 喜欢打铁的篮球菜鸟;

  • 喜欢历史的乏味少年;

  • 喜欢rap的五音不全弱鸡如果你想一起学习前端,一起摸鱼,一起研究简历优化,一起研究面试进步,一起交流历史音乐篮球rap,可以来俺的摸鱼学习群哈哈,点这个,有7000多名前端小伙伴在等着一起学习哦 --> 摸鱼沸点

  • 广州的兄弟可以约饭哦,或者约球~我负责打铁,你负责进球,谢谢~