当前位置: 首页 > news >正文

小米前端面试

这是一份针对您图片中列出的前端面试题目的详细解答。我将按照顺序,对每个问题提供清晰、深入的答案,并附上代码示例和对比总结,以帮助您全面准备。
在这里插入图片描述


1. 自我介绍

回答思路(模板):

面试官您好,我叫[您的姓名],是[您的学校] [您的专业]的应届生。我主要的技术方向是前端开发,熟练掌握 JavaScript(ES6+)、HTML5、CSS3,并有丰富的 Vue.js / React 实战经验。

在项目方面,我曾在[项目名称]中负责[具体职责,如“基于 Vue CLI 搭建前端架构,实现组件化开发”],并解决了[具体技术难点,如“首屏加载性能优化”]。我对前端工程化、性能优化和用户体验有浓厚的兴趣。

我非常期待能加入贵公司,与团队一起应对挑战。谢谢!

核心要点: 结构清晰、突出技术栈、结合项目经验、展现热情。


2. #06 有效的括号 (20)

这是一个经典的栈应用问题。给定一个只包括 '('')''{''}''['']' 的字符串,判断字符串是否有效。

解题思路:

  1. 使用数据结构。
  2. 遍历字符串,遇到左括号就将其压入栈中。
  3. 遇到右括号时:
    • 检查栈是否为空,若为空则直接返回 false
    • 将栈顶元素弹出,检查是否与当前右括号匹配。如果不匹配,返回 false
  4. 遍历结束后,检查栈是否为空。如果栈为空,说明所有括号都正确匹配,返回 true;否则返回 false

JavaScript 代码实现:

function isValid(s) {const stack = [];const map = {'(': ')','[': ']','{': '}'};for (let char of s) {if (map[char]) {// 如果是左括号,压入栈stack.push(char);} else {// 如果是右括号if (stack.length === 0) {return false; // 栈为空,不匹配}const top = stack.pop(); // 弹出栈顶的左括号if (map[top] !== char) {return false; // 弹出的左括号不匹配当前的右括号}}}// 最后栈必须为空才有效return stack.length === 0;
}// 测试
console.log(isValid("()")); // true
console.log(isValid("()[]{}")); // true
console.log(isValid("(]")); // false
console.log(isValid("([)]")); // false
console.log(isValid("{[]}")); // true

3. 两栏布局/三栏布局

两栏布局(左侧固定,右侧自适应)

方法1:Flexbox(最推荐)

<style>
.container {display: flex;height: 100vh;
}
.left {width: 200px; /* 固定宽度 */background: #ccc;
}
.right {flex: 1; /* 占据剩余所有空间 */background: #f0f0f0;
}
</style>
<div class="container"><div class="left">左侧固定</div><div class="right">右侧自适应</div>
</div>

方法2:Grid布局

.container {display: grid;grid-template-columns: 200px 1fr; /* 第一列200px,第二列自适应 */height: 100vh;
}
三栏布局(左右固定,中间自适应)

圣杯布局/双飞翼布局(经典,但现代开发中已较少使用)
方法:Flexbox(最简洁)

<style>
.container {display: flex;
}
.left, .right {width: 200px;background: #ccc;
}
.middle {flex: 1;background: #f0f0f0;
}
</style>
<div class="container"><div class="left">左侧固定</div><div class="middle">中间自适应</div><div class="right">右侧固定</div>
</div>

4. Flex 布局

Flexible Box 模型,是一种一维的布局模型,用于在一条直线上排列元素。

核心概念:

  • 容器:设置 display: flex; 的元素。
  • 项目:容器的直接子元素。
  • 主轴交叉轴

常用容器属性:

.container {display: flex;flex-direction: row; /* 主轴方向:row, row-reverse, column, column-reverse */justify-content: flex-start; /* 主轴对齐:center, space-between, space-around */align-items: stretch; /* 交叉轴单行对齐:flex-start, center, flex-end */flex-wrap: nowrap; /* 是否换行:wrap */
}

常用项目属性:

.item {flex-grow: 0; /* 放大比例 */flex-shrink: 1; /* 缩小比例 */flex-basis: auto; /* 项目初始大小 */flex: 1; /* 是 grow, shrink, basis 的简写 */align-self: auto; /* 单个项目在交叉轴上的对齐方式 */
}

5. Grid 布局

CSS Grid Layout 是一个二维的网格布局系统,将网页划分成网格,可以任意组合不同的网格。

核心概念:

  • 容器:设置 display: grid; 的元素。
  • 项目:容器的直接子元素。

常用容器属性:

.container {display: grid;grid-template-columns: 100px 1fr 2fr; /* 定义三列:第一列100px,第二列1份,第三列2份 */grid-template-rows: 50px 1fr; /* 定义两行 */gap: 10px; /* 网格间隙 */justify-items: stretch; /* 单元格内水平对齐 */align-items: stretch; /* 单元格内垂直对齐 */
}

常用项目属性:

.item {grid-column-start: 1;grid-column-end: 3; /* 项目占据从第1条网格线到第3条网格线 */grid-row: 1 / 3; /* 是 grid-row-start 和 grid-row-end 的简写 */
}

6. React Hooks

Hooks 是 React 16.8 引入的特性,让你在函数组件中使用 state 和其他 React 特性。

常用 Hooks:

  • useState:在函数组件中添加状态。
    import { useState } from 'react';
    function Example() {const [count, setCount] = useState(0);return (<div><p>You clicked {count} times</p><button onClick={() => setCount(count + 1)}>Click me</button></div>);
    }
    
  • useEffect:处理副作用(数据获取、订阅、手动修改DOM等)。
    useEffect(() => {// 相当于 componentDidMount 和 componentDidUpdatedocument.title = `You clicked ${count} times`;return () => {// 清理函数,相当于 componentWillUnmount};
    }, [count]); // 依赖数组,只有 count 变化时才执行
    
  • useContext:读取 Context。
  • useReducer:作为 useState 的替代方案,管理复杂 state 逻辑。

7. 实现的高阶组件 (HOC)

高阶组件是一个函数,它接受一个组件并返回一个新的组件。用于复用组件逻辑

示例:一个用于跟踪用户点击的高阶组件

function withClickTracker(WrappedComponent) {return function TrackedComponent(props) {const handleClick = (...args) => {console.log('Component was clicked!', props, args);// 这里可以发送数据到数据分析平台if (props.onClick) {props.onClick(...args);}};return <WrappedComponent {...props} onClick={handleClick} />;};
}// 使用
const MyButton = ({ onClick, children }) => (<button onClick={onClick}>{children}</button>
);
const TrackedButton = withClickTracker(MyButton);

8. 受控/非受控组件

受控组件

表单项的值由 React 的 state 控制,通过 onChange 事件更新 state。

function ControlledForm() {const [value, setValue] = useState('');const handleSubmit = (e) => {e.preventDefault();console.log(value);};return (<form onSubmit={handleSubmit}><input type="text" value={value} onChange={(e) => setValue(e.target.value)} /><button type="submit">Submit</button></form>);
}

优点:数据流清晰,易于验证和控制。

非受控组件

表单项的值由 DOM 自身管理,使用 ref 来获取值。

function UncontrolledForm() {const inputRef = useRef(null);const handleSubmit = (e) => {e.preventDefault();console.log(inputRef.current.value);};return (<form onSubmit={handleSubmit}><input type="text" ref={inputRef} /><button type="submit">Submit</button></form>);
}

优点:代码简单,更接近传统HTML。


9. Vue vs React

特性VueReact
设计哲学渐进式框架,官方提供全套解决方案,专注于视图层,依赖社区生态
模板语法基于 HTML 的模板,指令(如 v-if, v-forJSX(JavaScript 的语法扩展)
状态管理data 属性,响应式系统useState/useReducer Hooks,状态不可变
组件通信props 下行,$emit 上行props 下行,回调函数上行
学习曲线相对平缓,API 设计更直观相对陡峭,需要理解函数式编程概念
生态系统Vuex/Pinia(状态管理),Vue Router(路由)Redux/MobX(状态管理),React Router(路由)

选择建议:Vue 更适合追求开发效率和规范化的团队,React 更适合追求灵活性和函数式编程的团队。


10. Computed vs Watch (Vue)

Computed(计算属性)
  • 用途:基于依赖的响应式数据进行计算,并返回一个新的值。适用于需要根据现有数据衍生出新数据的场景。
  • 特点缓存结果。只有当其依赖的响应式数据发生变化时,才会重新计算。
  • 示例
    computed: {fullName() {return this.firstName + ' ' + this.lastName;}
    }
    
Watch(侦听器)
  • 用途观察一个特定的响应式数据源,并在其变化时执行副作用(如异步操作、复杂逻辑)。适用于数据变化时需要执行异步请求或开销较大的操作。
  • 特点无缓存,更通用,可以执行异步操作。
  • 示例
    watch: {searchQuery(newVal, oldVal) {if (newVal !== oldVal) {this.debouncedSearch();}}
    }
    

简单总结:想要一个衍生数据computed;想要在数据变化时做点什么watch


11. Vue Keep-alive 组件

<keep-alive> 是 Vue 的内置组件,用于缓存不活动的组件实例,而不是销毁它们。

作用:在组件切换时(如 Tab 切换、路由切换),保留组件的状态(如数据、滚动位置),避免重复渲染,提升性能。

基本用法

<template><keep-alive><component :is="currentComponent"></component></keep-alive>
</template>

常用属性

  • include:只有名称匹配的组件会被缓存。
  • exclude:任何名称匹配的组件都不会被缓存。
  • max:最多可以缓存多少组件实例。

生命周期钩子:被 <keep-alive> 包裹的组件会多出两个生命周期钩子:

  • activated():组件被激活时调用。
  • deactivated():组件被停用时调用。

12. Composition API vs Options API / Vue2 vs Vue3

Options API (Vue2 的主要写法)
  • 通过不同的选项(datamethodscomputedwatch生命周期)来组织代码。
  • 优点:结构清晰,易于初学者理解,逻辑按类型分组。
  • 缺点逻辑关注点分散。一个功能的代码可能分散在 datamethodsmounted 等多个地方。
Composition API (Vue3 的主要特性,Vue2.7 也支持)
  • 使用 setup() 函数和一系列函数(如 refreactiveonMounted)来组织代码。
  • 优点逻辑关注点集中。可以将一个功能的所有相关代码(状态、方法、生命周期)放在一起,更好的逻辑复用和代码组织(通过自定义函数)。
  • 示例
    import { ref, onMounted } from 'vue';
    export default {setup() {const count = ref(0);const increment = () => { count.value++; };onMounted(() => { console.log('component mounted'); });return { count, increment };}
    };
    

Vue2 vs Vue3 主要区别

  1. 性能:Vue3 使用 Proxy 重写响应式系统,性能更好,支持更大的组件树。
  2. Tree-shaking:Vue3 更好的支持,更小的打包体积。
  3. Composition API:Vue3 的默认推荐写法。
  4. Fragment、Teleport、Suspense:Vue3 新增的内置组件。

13. Vue 如何做懒加载?懒加载与滚动加载

懒加载 (Lazy Loading)

通常指路由懒加载组件懒加载,目的是减少初始包体积,加快首屏加载速度。

路由懒加载(使用 Vue Router)

// 静态导入
// import Home from '@/views/Home.vue'// 懒加载(动态导入)
const Home = () => import('@/views/Home.vue');
const About = () => import('@/views/About.vue');const routes = [{ path: '/', component: Home },{ path: '/about', component: About }
];

组件懒加载

<template><div><Suspense><template #default><LazyComponent /></template><template #fallback><div>Loading...</div></template></Suspense></div>
</template>
<script>
const LazyComponent = () => import('./LazyComponent.vue');
export default {components: { LazyComponent }
};
</script>
滚动加载 (Infinite Scroll)

指当用户滚动到页面底部或特定位置时,自动加载更多数据。常用于新闻Feed、商品列表等。

实现思路

  1. 监听滚动事件或使用 Intersection Observer API。
  2. 判断是否滚动到了“加载更多”的触发点(如距离底部100px)。
  3. 触发加载数据的函数,将新数据追加到现有列表。

懒加载 vs 滚动加载

  • 懒加载:关注的是代码资源的按需加载。
  • 滚动加载:关注的是数据内容的按需加载。

14. Vue 生命周期中错误处理的钩子函数

Vue 有专门的 错误捕获钩子 来捕获和处理组件树中的错误。

errorCaptured(生命周期钩子)
  • 捕获一个来自后代组件的错误时被调用。
  • 返回 false 可以阻止错误继续向上传播。
  • 示例
    errorCaptured(err, vm, info) {console.error('Error captured:', err, info);// 可以在此处上报错误到监控平台// return false; // 阻止错误继续向上传播
    }
    
Vue 3 的 onErrorCaptured (Composition API)
import { onErrorCaptured } from 'vue';
setup() {onErrorCaptured((err, vm, info) => {console.error('Error captured:', err, info);return false;});
}
全局错误处理:app.config.errorHandler (Vue 3)
const app = createApp(App);
app.config.errorHandler = (err, vm, info) => {// 全局捕获任何未被处理的错误console.error('Global error handler:', err, info);// 发送错误日志到服务器
};

15. Webpack vs Vite

特性WebpackVite
构建理念打包器 (Bundler)。先打包所有模块,再启动开发服务器。基于 ESM 的 No-Bundle。启动时按需编译和提供源码。
启动速度。项目越大,启动越慢。极快。无论项目大小,都是秒级启动。
HMR(热更新)速度较慢。需要重新构建部分 bundle。极快。仅精确更新修改的模块。
生产构建成熟稳定,优化手段丰富。使用 Rollup 进行构建,同样高效。
配置复杂度配置相对复杂,概念多(Loaders, Plugins)。配置更简单,开箱即用。
适用场景大型、复杂项目,需要高度自定义。现代浏览器项目,追求极速开发体验。

核心区别:Vite 利用浏览器原生 ES 模块的支持,在开发阶段避免了不必要的打包,从而获得了极致的性能。


16. 反问

这是你展示对公司和职位兴趣的好机会。可以问一些有深度的问题,例如:

  1. 关于团队与技术:
    • “我们团队目前主要的技术栈和未来的技术规划是怎样的?”
    • “目前团队遇到的最大技术挑战是什么?”
  2. 关于发展与成长:
    • “公司对新入职的应届生有哪些培养机制或 mentorship 计划?”
    • “这个岗位的晋升路径是怎样的?”
  3. 关于工作内容:
    • “如果我入职,前期会主要负责哪些业务或项目?”
  4. 关于文化:
    • “团队的工作氛围和沟通协作方式是怎样的?”

避免问:薪资、加班等过于直接或负面的问题(这些通常由 HR 后续沟通)。

希望这份详细的解答能帮助您顺利通过面试!


好的,这是针对“小米前端秋招一面”面试题目的逐一详细解答。我将结合核心概念、代码示例和面试回答要点,为您提供一份完整的参考答案。


1. 自我介绍

回答思路:结构清晰,突出技术栈、项目经验和与岗位的匹配度。
示例模板

面试官您好,我叫[你的名字],是[你的学校] [你的专业] 的应届生。我主要的技术方向是前端开发,熟练掌握 JavaScript、ES6+、Vue/React 等核心技术栈。

我尤其对 Web 图形学和数据可视化有浓厚的兴趣,并深入学习和实践了 Three.js 和相关 WebGL 知识。例如,在[某个项目]中,我使用 Three.js 实现了[某个具体功能,如“3D 楼宇的自动化生成和交互”],并通过[某项优化,如“几何体合并和 LOD”]来提升性能。

我非常期待能加入小米,在富有挑战的业务中贡献我的技术能力。谢谢!


2. JS 中箭头函数和普通函数的区别

这是 ES6 的基础核心考点。

特性普通函数箭头函数
this 指向动态绑定,取决于调用方式(谁调用它)词法绑定,继承自定义它时所在的作用域的 this
arguments 对象有,包含所有实参无,需用剩余参数 ...args
能否作为构造函数能,用 new 关键字不能,会抛出错误
原型 prototype
简写语法function() {}() => {}

代码示例

// this 指向的区别
const obj = {name: 'obj',regularFunc: function() { console.log(this.name); },arrowFunc: () => { console.log(this.name); }
};
obj.regularFunc(); // 'obj' (this 指向 obj)
obj.arrowFunc(); // undefined (this 指向全局对象或 undefined(严格模式))// 构造函数
function Person(name) { this.name = name; }
const p = new Person('Alice'); // 正确const Animal = (name) => { this.name = name; };
// const a = new Animal('Cat'); // TypeError: Animal is not a constructor// 参数对象
function regular() { console.log(arguments); }
regular(1, 2); // Arguments(2) [1, 2]const arrow = (...args) => { console.log(args); }; // 使用剩余参数
arrow(1, 2); // [1, 2]

面试回答要点重点强调 this 绑定的不同,并说明箭头函数因其简洁性和固定的 this,在回调函数(如事件处理、定时器)中特别有用。


3. ES6 有哪些新特性,说你认为比较重要的

选择几个最常用、影响最大的特性深入说明。

  1. letconst:块级作用域,解决 var 的变量提升和污染全局问题。
  2. 箭头函数:如上所述,简化写法,固定 this
  3. 模板字符串`Hello, ${name}!`,支持多行字符串和变量嵌入。
  4. 解构赋值const { a, b } = obj;const [first, second] = arr;,简化数据提取。
  5. 模块化(import/export:取代 require,成为前端模块标准,支持静态分析,利于 Tree Shaking。
  6. Promise:解决回调地狱,为异步编程提供更优雅的解决方案。
  7. Class:语法糖,让基于原型的继承写法更清晰、更像传统面向对象语言。

面试回答要点不要只罗列。挑 3-4 个你最熟悉的,说清楚它解决了什么问题,并给出简单例子。例如:“我认为 Promise模块化 非常重要。Promise 让我们告别了回调地狱,让异步代码的流程控制变得清晰可控。而 import/export 模块化是现代前端工程的基石,它支持静态优化,使得构建工具可以剔除无用代码(Tree Shaking),极大优化了打包体积。”


4. Promise 和 async/await 有什么关系

关系async/await 是建立在 Promise 之上的语法糖,其目的是为了让异步代码的写法更像同步代码,进一步提高可读性和可维护性。

  • async 函数总是返回一个 Promise 对象。
  • await 关键字后面通常是一个 Promise 对象,它会“等待”该 Promise 完成(resolve 或 reject),并返回其结果。

代码对比

// 使用 Promise
function fetchData() {return fetch('/api/data').then(response => response.json()).then(data => console.log(data)).catch(error => console.error(error));
}// 使用 async/await (功能完全相同,但更简洁)
async function fetchData() {try {const response = await fetch('/api/data');const data = await response.json();console.log(data);} catch (error) {console.error(error);}
}

面试回答要点async/await 并没有取代 Promise,它只是让使用 Promise 的代码更易写、易读。底层依然是 Promise 在工作。


5. 异步编程介绍一下

异步编程是指任务的执行不是连续的,不必等待上一个任务结束再执行下一个。这是为了避免阻塞主线程,保证 UI 的流畅响应。

演进历程

  1. 回调函数(Callback):最早的方式,容易导致“回调地狱”(Callback Hell),代码难以维护。
  2. Promise:ES6 引入,通过链式调用(.then().catch())扁平化了异步流程。
  3. Generator:ES6 引入,可以暂停执行的函数,配合执行器可用于异步控制,但较复杂。
  4. async/await:ES2017 引入,终极解决方案,以同步的方式写异步代码,可读性最强。

面试回答要点:讲清楚为什么需要异步(避免阻塞),以及从回调到 async/await 的演进过程,突出后者在可读性和可维护性上的优势。


6. 宏任务和微任务的区别

这是理解 Event Loop(事件循环)的核心。

类型代表任务触发时机
宏任务setTimeout, setInterval, setImmediate (Node), I/O, UI 渲染每次 Event Loop 循环中执行一个
微任务Promise.then/catch/finally, process.nextTick (Node), MutationObserver在每个宏任务执行完毕后,立即清空整个微任务队列

执行顺序规则一个宏任务 → 所有微任务 → UI渲染 → 下一个宏任务

代码示例

console.log('script start'); // 同步任务setTimeout(() => {console.log('setTimeout'); // 宏任务
}, 0);Promise.resolve().then(() => {console.log('promise1'); // 微任务}).then(() => {console.log('promise2'); // 微任务});console.log('script end'); // 同步任务// 输出顺序:
// 'script start'
// 'script end'
// 'promise1'
// 'promise2'
// 'setTimeout'

面试回答要点:一定要说出 “微任务的优先级高于宏任务” 以及 “在执行下一个宏任务前,必须清空当前的微任务队列”


7. ES6 代码如何保证在低版本浏览器运行?(Babel)

核心工具Babel
原理:Babel 是一个 JavaScript 编译器(或转译器)。

  1. 解析:将 ES6+ 代码解析成抽象语法树(AST)
  2. 转换:遍历 AST,将其中的新语法(如箭头函数、const)和新的 API(如 Promise, Array.from)转换成等价的 ES5 代码。
  3. 生成:将转换后的 AST 再生成回 ES5 代码。

补充:Polyfill:Babel 主要转译语法,对于新的全局对象(如 Promise)或实例方法(如 Array.prototype.includes),需要引入 core-js 等 Polyfill 库来模拟实现。

面试回答要点:Babel 负责语法转换,Polyfill 负责 API 模拟,二者结合才能完全兼容低版本浏览器。通常会与 Webpack 等构建工具集成。


8. 如何防止快速重复点击?(防抖与节流)

这是处理高频事件的经典优化手段。

  • 防抖:在事件被触发 n 秒后执行回调,如果在这 n 秒内又被触发,则重新计时。(最终只执行一次)
    • 场景:搜索框输入联想、窗口 resize 结束后的调整。
  • 节流:规定在一个单位时间内,只能触发一次函数回调。如果这个单位时间内触发多次,只有一次生效。(按固定频率执行)
    • 场景:滚动加载、按钮点击(防止重复提交)。

代码实现

// 防抖
function debounce(func, wait) {let timeout;return function (...args) {clearTimeout(timeout); // 清除之前的定时器timeout = setTimeout(() => func.apply(this, args), wait);};
}// 节流 (时间戳版)
function throttle(func, wait) {let lastTime = 0;return function (...args) {const now = Date.now();if (now - lastTime >= wait) {func.apply(this, args);lastTime = now;}};
}// 使用
const debouncedClick = debounce(() => console.log('Clicked!'), 500);
const throttledScroll = throttle(() => console.log('Scrolling!'), 200);

面试回答要点:清晰区分两者概念和适用场景。防抖是“回城”,节流是“技能冷却”。


9. JS 代码从编写到浏览器运行发生了什么?(V8 引擎)

这是一个宏观流程题,考察对 JS 运行机制的理解。

  1. 下载与解析:浏览器下载 .js 文件。
  2. 解析:V8 引擎的解析器将 JS 代码转换成抽象语法树(AST)
  3. 解释执行
    • 解释器(Ignition) 将 AST 转换成字节码并快速执行。
  4. 优化编译
    • 编译器(TurboFan) 在代码运行时监控热点函数(被多次执行),将其字节码编译成高度优化的机器码,极大提升后续执行速度。这就是 JIT(即时编译)
  5. 垃圾回收Orinoco 垃圾回收器自动管理内存,回收不再使用的对象。

面试回答要点:不要只提 V8,要说出 Ignition 解释器TurboFan 编译器的协同工作(JIT),这是 V8 性能的关键。


10. 一个函数从编写到调用执行会发生什么?(执行上下文栈)

过程

  1. 定义:JS 引擎在编译阶段识别函数声明,并将其存入内存。
  2. 调用:当函数被调用时,JS 引擎会创建一个该函数的执行上下文
  3. 执行上下文内容:包含三个核心部分:
    • 变量环境:存放 var 声明的变量和函数声明。
    • 词法环境:存放 let/const 声明的变量。
    • this 绑定
  4. 压栈:新创建的执行上下文会被压入调用栈顶部。
  5. 执行:在上下文中逐行执行函数体内的代码。
  6. 出栈:函数执行完毕,其执行上下文从调用栈弹出,控制权交还给栈中的上一个上下文。

为什么是栈结构?
因为函数的调用关系是后进先出的。例如,A 函数调用 B 函数,B 函数又调用 C 函数。C 执行完后必须先回到 BB 执行完再回到 A。栈结构的特性完美匹配了这种调用顺序。

面试回答要点:重点说清执行上下文的创建和压栈、出栈过程,并解释栈结构的后进先出特性与函数调用顺序的自然匹配。


11. 打包工具打包之后一般会有哪些产物?

以 Webpack 为例:

  1. JS Bundle:一个或多个被压缩、混淆的 .js 文件,是应用的核心代码。
  2. CSS Bundle:通常被提取为单独的 .css 文件(通过 mini-css-extract-plugin)。
  3. HTML 文件:通常是由 html-webpack-plugin 自动生成的 index.html,并已自动注入 JS 和 CSS 资源链接。
  4. 静态资源:如图片、字体,会被处理(压缩、重命名)后输出到特定目录(如 assets/)。
  5. Source Map:用于生产环境调试的 .map 文件,将压缩后的代码映射回源代码。
  6. 模块联邦等运行时文件

面试回答要点:说出主要的 JS、CSS、HTML 文件,并可以提一下静态资源和 Source Map。


12. 一次性发送多个请求,统一处理结果有哪些方式?(除了 Promise.all)

这是在考察你对 Promise 其他静态方法的了解。

  1. Promise.allSettled:等待所有 Promise 完成(无论成功或失败),返回一个数组,描述每个 Promise 的结果。适用于不关心单个请求成败,但需要知道所有结果的场景(如批量数据上报)。
    const promises = [fetch(url1), fetch(url2)];
    Promise.allSettled(promises).then(results => {results.forEach(result => {if (result.status === 'fulfilled') {console.log('成功:', result.value);} else {console.log('失败:', result.reason);}});
    });
    
  2. Promise.race:返回第一个完成(成功或失败)的 Promise 的结果。适用于竞速或超时控制
    const timeoutPromise = new Promise((_, reject) => setTimeout(() => reject('超时'), 5000));
    Promise.race([fetch(url), timeoutPromise]).then(data => console.log(data)).catch(err => console.error(err)); // 如果 fetch 超过5秒,这里会捕获‘超时’
    
  3. Promise.any:返回第一个成功的 Promise 的结果。如果全部失败,则返回一个聚合错误。适用于多源备份,只要一个成功即可

面试回答要点:明确说出 allSettledraceany 这三者与 all 的区别和各自的应用场景。


13. 项目中如何捕获错误,生产环境怎么做?

开发环境

  • 代码层面:使用 try...catch 捕获同步错误,使用 .catch() 捕获 Promise 错误。
  • 工具层面:利用浏览器的开发者工具(Console, Debugger)直接查看和定位错误。

生产环境

  1. 全局错误监控
    // 全局错误
    window.addEventListener('error', (event) => {// 将 event.error 信息上报到服务器reportError(event.error);
    });
    // Promise 错误
    window.addEventListener('unhandledrejection', (event) => {reportError(event.reason);
    });
    
  2. 错误上报:构建一个上报接口,将错误的堆栈信息、用户环境、发生时间等发送到日志服务器。
  3. 使用监控平台:接入 SentryFundebug 等第三方前端监控服务,它们提供了完整的错误收集、聚合、分析和告警功能。

面试回答要点:区分开发和生产环境的不同做法。生产环境的核心是 “全局监听 + 上报机制”,最好能提到 Sentry 这样的专业工具。


14. importrequire 的区别

特性require (CommonJS)import (ES Module)
本质运行时加载,是一个函数调用编译时加载(静态化),是一个关键字
加载方式同步加载异步加载
位置可放在代码任何位置必须放在模块顶层(目前),不能嵌套在条件语句中
赋值动态的,可以解构 const { a } = require(‘mod’)静态的,编译时就能确定依赖关系
性能/优化无法在编译时做优化支持 Tree Shaking(摇树优化),剔除未引用代码
值类型导出的是值的拷贝导出的是值的引用(只读)

面试回答要点:最核心的区别是 “动态” vs “静态”import 的静态特性使得构建工具可以进行 Tree Shaking,这是现代前端工程优化的关键。


15. 手撕:猴子找大王(约瑟夫环问题)

这是一个经典的算法问题。最优解法是使用数学公式,但面试中更常考察模拟过程的实现。

题目:m 只猴子坐一圈报数,报到 n 的出列,求最终剩下的索引。

思路:使用一个数组模拟猴子圈,循环报数,每次移除报到 n 的猴子,直到只剩一只。

代码实现

function find(m, n) {// 1. 初始化猴子数组 [0, 1, 2, ..., m-1]const monkeys = Array.from({ length: m }, (_, i) => i);// 2. 初始化报数索引let countIndex = 0;// 3. 循环,直到只剩一只猴子while (monkeys.length > 1) {// 4. 计算当前轮次要出列的猴子索引: (当前开始位置 + 数 n-1 步) % 当前剩余猴子数// 因为从1开始数,数到n,实际是移动 n-1 步countIndex = (countIndex + n - 1) % monkeys.length;// 5. 移除该猴子monkeys.splice(countIndex, 1);// 注意:splice 后,countIndex 自然指向了下一位猴子的位置,无需额外+1}// 6. 返回最后剩下的猴子索引return monkeys[0];
}// 测试
console.log(find(5, 3)); // 输出 3
// 过程模拟: 初始 [0,1,2,3,4]
// 第1轮: 数到3,移除2 -> [0,1,3,4],从3开始数
// 第2轮: 数到3,移除0 -> [1,3,4],从1开始数
// 第3轮: 数到3,移除4 -> [1,3],从1开始数
// 第4轮: 数到3,移除1 -> [3]

更优的数学递归解法(时间复杂度 O(m)):

function find(m, n) {if (m === 1) return 0;return (find(m - 1, n) + n) % m;
}
// 思路:已知 m-1 只猴子时的大王索引,反推 m 只猴子时的大王索引。

面试回答要点:可以先给出模拟解法,如果面试官追问效率,再引出数学解法,体现你的思维深度。

希望这份详细的解答能帮助你顺利通过面试!

http://www.dtcms.com/a/542755.html

相关文章:

  • 用仿站软件做的网站seo如何管理信息系统有哪些
  • 织梦网站安装dir深圳宝安高端网站建设报价
  • 做阿里巴巴网站公司怎么分享网站
  • DRAM缓存与HMB技术谁更适合工业应用?天硕工业级SSD固态硬盘提供参考
  • 企业网站首页设计原则付银行的网站建设费的会计科目
  • 网站空间国外那个好新网站百度seo如何做
  • 推广网站模板网站后台根据前端做吗
  • MSYS2+VS Code中创建c++项目
  • 岳阳网站设计改版爱企查企业信息查询官网
  • 做直播网站找哪个网站开发协议书
  • 专注徐州网站开发怎么做电影网站的
  • 网站建设信息发布超简洁WordPress
  • 蒙古文政务网站群建设工作方案计算机基础培训机构
  • 汽车网站建设需要多少钱制作一个网站的全过程
  • 富阳网站建设洛洛科技wordpress3.8模板
  • 深圳网站建设外贸做视频网站服务器怎么选择
  • 企业网站最底下做的是什么找人做网站都需要提供什么
  • 手机代码网站有哪些问题吗北京便宜做网站
  • 网站重要三要素三门峡做网站推广
  • Unity UGC IDE实现深度解析(二):端口系统与类型安全机制
  • 怎么建设自己网站首页网络开发理论
  • 网站建设可实施性报告众筹网站搭建
  • 做网站和游戏是如何赚钱网上国网推广方案
  • 一个专门做特产的网站自己制作免费网页
  • 网站域名使用怎么做待摊分录做网站书
  • 网站设计的一般步骤是什么?做网站子页
  • 延吉市住房城乡建设局官方网站域名是干嘛的
  • 抖音点赞自助网站什么是优化网站
  • FreeRTOS队列实战:血氧监测系统设计
  • vscode使用verilog format插件教程