【前端面试4】框架以及TS

文章目录

  • 前言
    • [1. 什么是 AST(抽象语法树)?](#1. 什么是 AST(抽象语法树)?)
    • [2.Vue 的 SFC 是什么?如何最大化利用?](#2.Vue 的 SFC 是什么?如何最大化利用?)
    • [3. SSR 是什么?如何使用?](#3. SSR 是什么?如何使用?)
    • [4. Vue2 为什么无法监听数组变化,该如何做?](#4. Vue2 为什么无法监听数组变化,该如何做?)
    • [5.keep-alive 是什么?react 如何实现类似功能?](#5.keep-alive 是什么?react 如何实现类似功能?)
    • [6. 什么时候用计算属性,什么时候用监听?](#6. 什么时候用计算属性,什么时候用监听?)
    • [7. JS 中生成器和迭代器是什么,实际有什么应用?](#7. JS 中生成器和迭代器是什么,实际有什么应用?)
    • [8. 什么是 TS 的 infer?如何使用?](#8. 什么是 TS 的 infer?如何使用?)
    • 9.简要描述vite的原理
    • [10. 简要说明如何最大支持 Tree Shaking?](#10. 简要说明如何最大支持 Tree Shaking?)
    • 11.用math.random来计算抽奖概率会有什么问题?

前言

大家好,今天是冲击中级工程师第四天,让我们来完成今天的面试题打卡。

1. 什么是 AST(抽象语法树)?

答案:编译器(如 Babel、Webpack)无法直接修改你的代码字符串。它们必须先把代码转换成一种树状结构(JSON对象),这棵树精确地描述了代码的每一个部分(变量名、操作符、函数体)。如系列2所示,流程:源代码 -> 词法分析(Token) -> 语法分析 -> AST -> 修改/转换 -> 生成新代码。

下面代码可以很直观看到AST和我们编写代码的区别

javascript 复制代码
// 源代码
const a = 1;

// 对应的 AST (简化)
{
  "type": "VariableDeclaration", // 这是一个变量声明
  "kind": "const",               // 类型是 const
  "declarations": [
    {
      "type": "VariableDeclarator",
      "id": { "type": "Identifier", "name": "a" }, // 变量名 a
      "init": { "type": "Literal", "value": 1 }    // 初始值 1
    }
  ]
}

2.Vue 的 SFC 是什么?如何最大化利用?

答案:SFC,全称为:Single File Component,直译为单文件组件,是 Vue 的核心概念之一,指把一个组件的结构、逻辑、样式写在同一个 .vue 文件中。

下面是一个典型的SFC文件:

html 复制代码
<template>
  <div>{{ msg }}</div>
</template>

<script setup>
import { ref } from 'vue'

const msg = ref('Hello SFC')
</script>

<style scoped>
div {
  color: red;
}
</style>

vue这样做的优点:

1.高内聚:模板 + 逻辑 + 样式放在一起,方便维护

2.可编译优化:Vue 编译器可做静态提升、patch flag 等优化

3.强工程化支持:TS、CSS 预处理器、HMR、lint、tree-shaking

4.组件级作用域样式:避免样式污染

3. SSR 是什么?如何使用?

SSR,全称为Server-Side Rendering,服务端渲染,主要是指页面在服务器上先渲染成完整 HTML,再返回给浏览器展示,而不是等 JS 在浏览器执行后再生成页面。

以往都是客户端渲染,对比客户端渲染

CSR (客户端渲染):浏览器请求页面 -> 拿到空的 HTML -> 下载 JS -> JS 运行并把内容填进页面(首屏慢,爬虫抓不到内容)。

SSR (服务端渲染):浏览器请求页面 -> 服务器运行 Vue -> 生成完整的 HTML 字符串 -> 浏览器直接显示(首屏快,SEO 好)

如何使用?

vue可以使用Nuxt,打开SSR,React可以使用Next

4. Vue2 为什么无法监听数组变化,该如何做?

答案:Vue2 基于 Object.defineProperty,无法监听数组索引和 length 的变化,因此不能通过 arr[index] 或修改 length 触发更新。Vue2 通过重写数组的 7 个变异方法(push, pop, shift, unshift, splice, sort, reverse。只要你调用这 7 个方法,Vue 就能监听到)来实现数组响应式。正确做法是使用 splice 或 Vue.set。Vue3 是基于 ES6 Proxy(代理) 实现响应式,通过拦截对象和数组的所有基本操作(get / set / deleteProperty / has / ownKeys 等),统一做依赖收集和派发更新,因此可以完整监听数组索引、length 变化以及属性新增删除,不再需要像 Vue2 那样重写 Array 原型方法。

javascript 复制代码
//  错误做法 (Vue2 不会更新视图)
this.list[0] = '新的值';

//  正确做法 1: 使用重写的方法
this.list.splice(0, 1, '新的值');

//  正确做法 2: 使用 $set
this.$set(this.list, 0, '新的值');

5.keep-alive 是什么?react 如何实现类似功能?

答案:keep-alive 是 Vue 提供的内置抽象组件,用于在组件切换时缓存组件实例,而不是销毁,从而保留组件内部状态并减少重复创建带来的性能开销。被 keep-alive 包裹的组件不会触发 unmounted,而是通过 activated 和 deactivated 生命周期进行激活与失活。内部基于 key 维护缓存 Map,并通过 LRU 策略结合 max 属性控制缓存上限。

React 没有官方等价能力,因为 React 的设计是组件不在渲染树中就会被卸载。实际项目中通常通过样式隐藏、状态上提,或使用 react-activation 等第三方库来模拟组件缓存行为。

6. 什么时候用计算属性,什么时候用监听?

答案:computed 用于从已有响应式状态派生出新的状态,适合纯计算场景,具有缓存能力,依赖不变不会重复计算,强调声明式的数据关系。watch 用于在数据变化后执行副作用,比如发起接口请求、修改其他状态、路由跳转或与第三方库交互,属于命令式响应。原则上能用 computed 解决的派生数据不应该用 watch,watch 不用于计算新值,而用于处理变化带来的行为。

javascript 复制代码
// 场景:购物车总价 -> 用 Computed
const total = computed(() => price.value * count.value);

// 场景:搜索框输入停止 1秒 后自动搜索 -> 用 Watch
watch(searchText, (newVal) => {
  setTimeout(() => { api.search(newVal) }, 1000);
});

7. JS 中生成器和迭代器是什么,实际有什么应用?

答案:Iterator 是 ES 提供的统一遍历协议,通过 next 方法返回 value 和 done,使不同数据结构可以被 for...of、解构和扩展运算符统一遍历。Generator 是一种可以暂停和恢复执行的函数,用来更方便地创建迭代器,Generator 本身自动实现了 Iterator 和 Iterable 接口。它们的核心价值在于统一遍历接口、支持惰性计算以及可暂停的控制流。在工程中,Iterator 广泛用于 for...of 等语言特性,Generator 常用于自定义可遍历结构、惰性序列,以及在 redux-saga、Koa v1 等场景中用于复杂异步流程控制和流程编排。

实际使用示例:

javascript 复制代码
async function fetchUsers(page: number, pageSize: number) {
  const res = await fetch(`/api/users?page=${page}&pageSize=${pageSize}`)
  const data = await res.json()
  return data.list as User[]
}

async function* userIterator(pageSize = 100) {
  let page = 1

  while (true) {
    const list = await fetchUsers(page, pageSize)

    if (!list.length) {
      return
    }

    for (const user of list) {
      yield user   // 每次只 yield 一个用户
    }

    page++
  }
}

8. 什么是 TS 的 infer?如何使用?

答案:infer 是 TypeScript 条件类型中的关键字,用于在类型匹配过程中声明一个待推断的类型变量,从复杂类型结构中反向提取子类型。它常用于从函数类型中推断返回值和参数类型,从 Promise 中拆解返回值,从数组和元组中提取元素类型,以及在字符串模板类型中提取子串。TypeScript 内置的 ReturnType、Parameters、Awaited 等高级工具类型本质上都是基于 infer 实现的。infer 的核心价值是让类型具备模式匹配和结构拆解能力,从而减少重复类型定义并提升类型系统的表达能力。

例子(提取函数参数)

javascript 复制代码
type FnInfo<T> =
  T extends (...args: infer P) => infer R
    ? { params: P; return: R }
    : never

type Info = FnInfo<(id: number, name: string) => boolean>
// { params: [number, string]; return: boolean }

9.简要描述vite的原理

答案:Vite 在开发阶段基于浏览器原生 ES Module,通过 dev server 按需编译源码,不做全量打包,因此冷启动和热更新非常快。同时使用 esbuild 对第三方依赖进行预构建,统一为 ESM 并减少请求数量。在生产环境,Vite 使用 Rollup 进行静态打包,负责 Tree Shaking、代码分割和资源优化,从而兼顾开发体验和生产性能。

10. 简要说明如何最大支持 Tree Shaking?

答案:Tree Shaking 是基于 ES Module 静态分析的打包优化技术,用于在构建阶段移除未被使用的导出代码。它依赖 import/export 语法和无副作用模块设计,配合 sideEffects 标记和代码压缩工具,可以显著减少最终 bundle 体积并提升加载性能。

1.基于 ES Module 的命名导出 API确保项目是基于ES Module来进行的。

2.尽量用 export const func = ... 导出单个函数,而不是 export default { ... } 导出一个大对象(大对象很难被拆分优化)。

11.用math.random来计算抽奖概率会有什么问题?

答案:V8 引擎(Chrome/Node.js)底层使用的是 xorshift128+ 算法。这是一种确定性算法。只要拿到足够的历史数据序列,就能推算出内部状态(Seed),从而预测未来所有的随机数。对于涉及真金白银的抽奖,这是巨大的漏洞。虽然现代浏览器的算法改进了很多,但在某些特定数值范围内,Math.random() 并不是完美的均匀分布

解决方案:使用安全伪随机数生成器 (CSPRNG)

javascript 复制代码
// 1. 创建一个容器存放随机数
const array = new Uint32Array(1);
// 2. 填充真正的随机数 (基于物理噪声)
window.crypto.getRandomValues(array);
// 3. 归一化处理 (这一步比较复杂,简化理解为取模)
const winnerIndex = array[0] % userCount;

#总结

今天面试题就到这里,让我们每天学习几个题,一起成长。管他难易,获得成长就好。明天见。

相关推荐
callJJ17 小时前
深入浅出 MVCC —— 从零理解 MySQL 并发控制
数据库·mysql·面试·并发·mvcc
慧一居士17 小时前
vite 使用说明和示例演示
前端
牢七17 小时前
反序列化重点模块 private Object readOrdinaryObject(boolean unshared)废案与反思
java·服务器·前端
银发控、18 小时前
MySQL覆盖索引与索引下推
数据库·mysql·面试
NEXT0618 小时前
数组转树与树转数组
前端·数据结构·面试
We་ct18 小时前
浏览器 Reflow(重排)与Repaint(重绘)全解析
前端·面试·edge·edge浏览器
笨笨狗吞噬者18 小时前
【uniapp】小程序端解决分包的uni_modules打包后产物进入主包中的问题
前端·微信小程序·uni-app
WebInfra18 小时前
Modern.js 3.0 发布:聚焦 Web 框架,拥抱生态发展
前端·javascript·前端框架
AngelPP18 小时前
OpenClaw Memory 模块完整分析
前端·aigc·ai编程
ID_1800790547318 小时前
淘宝商品详情 API 接口 item_get: 高效获取商品数据的技术方案
java·前端·数据库