聚思力前端面经

781 阅读5分钟

成都聚思力一面

写一个获取 obj key 函数

简介:获取对象所有外层的 key,以新的对象形式进行输出

// 输入
const temp = {
    a: {
        b: {
            c:1
        }
    },
    d: 2
}
// 输出
{
    "a.b.c":"1",
    "d":"2"
}

本质上还是递归,定义好出口,利用参数传递 key。

function getKey(obj, temp = '') {
  if (typeof obj !== 'object') {
    return {
      temp: obj
    }
  }
  let result = {}
  for (const [key, val] of Object.entries(obj)) {
    if (typeof val === 'object') {
      result = { ...result, ...getKey(val, temp ? temp + '.' + key : key) }
    } else {
      result[temp ? temp + '.' + key : key] = val
    }
  }
  return result
}

vue3 和 vue2 有什么区别

回答这类问题最好理清楚几种纬度进行回答,但是最好不要回答自己不太熟悉的东西,以防止追问,回答不上的情况。

更快

基于 proxy 的响应系统实现更低加载内存以及提高加速速度

vue2 利用 Object.definePrototype进行数据劫持,进行依赖收集、通知变更。每次进行初始化 data 函数里的对象时,都要递归调用observe方法,进行产生 dep ,这个过程都会产生闭包,所以加载速度以及内存暂用都会更高。

vue3基于 Proxy的响应式系统,是处于懒劫持的过程,所以性能会更好,并且 Proxy是监听一个对象的变化,所以不需要像 vue2 那样有一些额外的 api 去补充响应式(set、delete)。

静态属性以及静态树相关提升

vue2针对静态相关的都会在 render 函数上声明上static

而 vue3 将静态相关提至公共部分,典型的内存换时间做法。

虚拟 DOM 重写

具体做法不太清楚

更多的编译时提示来减少运行时开销,使用更有效的代码来创建虚拟节点。 组件快速路径+单个调用+子节点类型检测。

优化 slots 生成

这个暂时不太了解

  • 确保实例正确的跟踪依赖关系
  • 避免不必要的父子组件重新渲染

响应式抽取

将响应式包(reactivity)抽取了出来,使得响应式相关模块解耦,更加模块化。

更小

Tree shaking 是一种通过清除多余代码方式来优化项目打包体积的技术,专业术语叫 Dead code elimination

vue2 中由于采用 options 写法等因素,打包时无法检测出哪些代码被使用过了。而vue3 中由于采用更加模块化的分类在加上使用 ES Module,通过静态编译知晓哪些 api 具体被使用过,从而实现Tree shaking

开发使用更加好用

  1. 对 TS 支持更加好(脚本以及模板)
  2. 不必像 vue2 一样考虑响应式的特殊情况(新增 key,删除 key)
  3. Volar IDE 插件更加友好的提示

vue3 是如何优化静态节点的识别

vue3 提升了静态节点至顶部,典型的空间换区时间操作,例如:

<div>
    <span class="foo">
        Static
    </span>
    <span>
        {{dynamic}}
    </span>
</div>
const __static1 = h('span',{
       class: 'foo'
}, 'static')

render() {
    return h('div',[
        __static1,
        h('span',this.dynamic)
    ])
}

什么是抽象语法树

该问题旨在问 vue 中的 compile 阶段。

compile 编译可以分成 parseoptimizegenerate 三个阶段,最终需要得到 render function。

首先是 parseparse 会用正则等方式将 template 模板中进行字符串解析,得到指令、class、style等数据,形成 AST。这里会大量运行正则去进行字符串解析最终清晰地描述出标签的属性以及依赖关系。

然后是optimize阶段,会对 AST 进行优化,会对静态节点进行标记。

最后是generate阶段,将 AST 处理后染回 render function。

npm yarn pnpm 有什么区别

npm3+之前,node_modules 中的每个依赖项都有自己的node_modules文件夹,在package.json中指定了所有的依赖项。这样的结构是干净、可预测的,但是这样会创建过深的依赖树以及会同一份依赖可能会被多次复制粘贴散落在各处。

在 npm3+和 yarn 中,后续采用了扁平安装。所谓的扁平安装为:依赖会被提升到顶层,如果有不同版本的同一依赖被安装,首个依赖会被提升,但是后续依赖还是像之前安装在各自的依赖当中。

另外yarn 还支持并行下载,会更快的下载依赖。也支持 workspace,让项目支持 monoreop

但是 npm3+ 以及 yarn 都会暴露出一个问题: 由于只有首个依赖会被提升,那么还是有可能会重复下载依赖。

pnpm 采用目录树结构加一个.pnpm文件夹进行管理依赖,.pnpm文件夹里已平铺形式保存着所有的包,然后利用Store + Links 进行文件资源进行关联。pnpm 会利用 store 储存资源在磁盘上的存储位置,再通过复制包或者硬链接、软链接设置过去。

npm 软链接平时使用过吗

指的是:npm link

我们平时可以使用npm link进行软链接,进行脚本或者依赖调试。

软链接会额外创建一个inode指向源文件的inode,类似快捷方式的感觉。而硬链接则是指向源文件的inode

next.js 有几种模式,为什么能返回 html?

  • 客户端渲染 CSR (Client Side Render)
  • 静态页面生成 SSG (Static Site Generation)
  • 服务端渲染 SSR (Server Side Render)
  • 增量静态再生 ISR(Incremental Static Regeneration)

这块不太了解

说一下动画帧,对比 setTimeout 有什么优点

requestAnimationFrame 会把每一帧中的所有DOM操作集中起来,在一次重绘或回流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率,一般来说,这个频率为每秒60帧。

在隐藏或不可见的元素中,requestAnimationFrame将不会进行重绘或回流,这当然就意味着更少的的cpu,gpu和内存使用量。

平时的开发流程

主要回答的两个方面:commitLint 以及 git 分支规范

commitLint 主要遵守 Angular 团队规范,利用git cz命令生成提交模板即可

git 分支理清楚:feature、release、bugfix、hotfix、devlop、master 几种分支区别即可。