前端开发高频面试题解析与实战技巧

一、正则表达式在文本处理中的应用

1.1 中英文符号转换场景

在数据处理过程中,常遇到JSON字符串中混用中英文标点符号的情况。例如将中文冒号、引号“”转换为英文符号:""。此类需求可通过正则表达式高效实现:

  1. function replaceChineseSymbols(str) {
  2. return str.replace(/:/g, ':')
  3. .replace(/“/g, '"')
  4. .replace(/”/g, '"');
  5. }
  6. // 测试用例
  7. const jsonStr = '{“name”: “张三”, “age”: 20}';
  8. console.log(replaceChineseSymbols(jsonStr));
  9. // 输出: {"name": "张三", "age": 20}

实现要点

  • 使用String.prototype.replace()方法配合正则全局匹配标志g
  • 通过字符类[]匹配特定符号,避免转义字符干扰
  • 建议对用户输入做双重校验,先标准化符号再解析JSON

1.2 复杂文本清洗方案

对于包含多种特殊符号的文本,可构建正则表达式组合:

  1. const symbolMap = {
  2. ':': ':',
  3. '“': '"',
  4. '”': '"',
  5. ';': ';',
  6. ',': ','
  7. };
  8. function advancedReplace(str) {
  9. let regex = new RegExp(Object.keys(symbolMap).join('|'), 'g');
  10. return str.replace(regex, match => symbolMap[match]);
  11. }

二、JavaScript异步编程进阶

2.1 Promise链式调用优化

在处理多个异步操作时,传统回调嵌套会导致”回调地狱”。使用Promise可显著提升代码可读性:

  1. // 模拟异步API调用
  2. function fetchData(url) {
  3. return new Promise(resolve => {
  4. setTimeout(() => resolve(`Data from ${url}`), 1000);
  5. });
  6. }
  7. // 顺序执行
  8. fetchData('/api/user')
  9. .then(data => {
  10. console.log(data);
  11. return fetchData('/api/orders');
  12. })
  13. .then(data => console.log(data));

2.2 并行控制最佳实践

当需要同时发起多个异步请求时,Promise.all()是理想选择:

  1. const apiList = ['/api/users', '/api/products', '/api/orders'];
  2. Promise.all(apiList.map(url => fetchData(url)))
  3. .then(results => {
  4. const [users, products, orders] = results;
  5. console.log({users, products, orders});
  6. })
  7. .catch(error => console.error('Request failed:', error));

注意事项

  • 某个请求失败会导致整个Promise.all()被拒绝
  • 对关键请求建议单独处理,非关键请求可使用Promise.allSettled()

2.3 异步生成器实现

对于需要逐步处理大数据流的场景,可使用异步生成器:

  1. async function* streamProcessor(dataStream) {
  2. for await (const chunk of dataStream) {
  3. const processed = await processChunk(chunk);
  4. yield processed;
  5. }
  6. }
  7. // 使用示例
  8. (async () => {
  9. const stream = getDataStream(); // 获取数据流
  10. for await (const data of streamProcessor(stream)) {
  11. console.log(data);
  12. }
  13. })();

三、核心算法实现解析

3.1 两数之和问题

给定数组和目标值,找出相加等于目标值的两个元素索引:

  1. // 双指针解法(适用于已排序数组)
  2. function twoSumSorted(numbers, target) {
  3. let left = 0, right = numbers.length - 1;
  4. while (left < right) {
  5. const sum = numbers[left] + numbers[right];
  6. if (sum === target) return [left, right];
  7. sum < target ? left++ : right--;
  8. }
  9. return [-1, -1];
  10. }
  11. // 哈希表解法(通用场景)
  12. function twoSum(nums, target) {
  13. const map = new Map();
  14. for (let i = 0; i < nums.length; i++) {
  15. const complement = target - nums[i];
  16. if (map.has(complement)) return [map.get(complement), i];
  17. map.set(nums[i], i);
  18. }
  19. return [-1, -1];
  20. }

复杂度分析

  • 双指针法:时间复杂度O(n),空间复杂度O(1)
  • 哈希表法:时间复杂度O(n),空间复杂度O(n)

3.2 数组反转实现

基础反转算法需注意边界条件处理:

  1. // 原地反转(空间复杂度O(1))
  2. function reverseArray(arr) {
  3. let left = 0, right = arr.length - 1;
  4. while (left < right) {
  5. [arr[left], arr[right]] = [arr[right], arr[left]];
  6. left++;
  7. right--;
  8. }
  9. return arr;
  10. }
  11. // 创建新数组(保持原数组不变)
  12. function reverseCopy(arr) {
  13. const result = [];
  14. for (let i = arr.length - 1; i >= 0; i--) {
  15. result.push(arr[i]);
  16. }
  17. return result;
  18. }

四、对象操作高级技巧

4.1 对象合并策略

Object.assign()方法存在浅拷贝限制,深拷贝需结合其他方案:

  1. // 浅合并
  2. const target = { a: 1 };
  3. const source = { b: 2, c: { d: 3 } };
  4. Object.assign(target, source);
  5. // target变为 {a:1, b:2, c:{d:3}},但c是引用
  6. // 深合并实现
  7. function deepMerge(target, ...sources) {
  8. sources.forEach(source => {
  9. for (const key in source) {
  10. if (source[key] instanceof Object && !Array.isArray(source[key])) {
  11. target[key] = deepMerge(target[key] || {}, source[key]);
  12. } else {
  13. target[key] = source[key];
  14. }
  15. }
  16. });
  17. return target;
  18. }

4.2 对象属性遍历顺序

ES6规范定义了对象属性遍历顺序规则:

  1. 数字键按升序排列
  2. 字符串键按添加顺序排列
  3. Symbol键按添加顺序排列
    ```javascript
    const obj = {

2: ‘two’,
a: ‘a’,
1: ‘one’,
b: ‘b’
};

Object.getOwnPropertyNames(obj); // [“1”, “2”, “a”, “b”]
Reflect.ownKeys(obj); // [“1”, “2”, “a”, “b”, Symbol(id)]

  1. ### 五、性能优化实践
  2. #### 5.1 防抖与节流实现
  3. 控制高频事件触发的经典方案:
  4. ```javascript
  5. // 防抖函数(最后触发)
  6. function debounce(fn, delay) {
  7. let timer = null;
  8. return function(...args) {
  9. clearTimeout(timer);
  10. timer = setTimeout(() => fn.apply(this, args), delay);
  11. };
  12. }
  13. // 节流函数(固定频率触发)
  14. function throttle(fn, interval) {
  15. let lastTime = 0;
  16. return function(...args) {
  17. const now = Date.now();
  18. if (now - lastTime >= interval) {
  19. fn.apply(this, args);
  20. lastTime = now;
  21. }
  22. };
  23. }

5.2 虚拟列表实现原理

处理长列表渲染性能问题的关键技术:

  1. class VirtualList {
  2. constructor(container, options) {
  3. this.container = container;
  4. this.itemHeight = options.itemHeight;
  5. this.visibleCount = Math.ceil(container.clientHeight / this.itemHeight);
  6. this.startIndex = 0;
  7. this.endIndex = this.visibleCount;
  8. // 实际实现需处理滚动事件和DOM更新
  9. }
  10. }

优化要点

  • 只渲染可视区域内的元素
  • 使用绝对定位控制元素位置
  • 监听滚动事件动态更新显示范围

本文系统梳理了前端开发中的高频面试考点,通过代码示例和实现原理分析,帮助开发者建立完整的知识体系。掌握这些核心概念不仅能提升面试表现,更能在实际项目中编写出更健壮、高效的代码。建议结合具体业务场景进行实践,加深对技术原理的理解。