0

两年经验前端:字节跳动系—石墨文档面经

 2 years ago
source link: https://segmentfault.com/a/1190000041355537
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

两年经验前端:字节跳动系—石墨文档面经

发布于 1 月 29 日

今天给大家分享一个字节跳动系公司——石墨文档的面经吧!废话不多说,先看题目!

  • 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: {   b: 1,   c: 2,   d: {    e: 5   }  },   b: [1, 3, {a: 2, b: 3}],   c: 3 }

    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-34+5/24+10/5',现在需要将高优先级运算,用小括号包裹起来,例如结果为 '11+2-(34)+(5/2*4)+(10/5)'。注意可能会出现连续的乘除运算,需要包裹到一起。 请用 javascript 实现这一过程
  • 1、手写体:使用TypeScript 实现一个 get 函数来获取它的属性值

    const data = { name: 'tom', age: 18, address: '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: {   b: 1,   c: 2,   d: {    e: 5   }  },   b: [1, 3, {a: 2, b: 3}],   c: 3 }

    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) => {
    return typeof 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-34+5/24+10/5',现在需要将高优先级运算,用小括号包裹起来,例如结果为 '11+2-(34)+(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++
    }else if (jType === 'low' && high) {
      res.push(j++)
      i = j++
      high = false
    }else if (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', age: 18, address: 'xxx' }
const get = <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', age: 18 }
    
    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
    })

由于本人React太菜,所以不敢答题有关React的题目

我是林三心,一个热心的前端菜鸟程序员。如果你上进,喜欢前端,想学习前端,那咱们可以交朋友,一起摸鱼哈哈,摸鱼群,加我请备注【思否】

image.png


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK