前端面试高频题解析

JavaScript 基础

闭包

闭包是指函数能够访问其词法作用域中的变量,即使函数在该作用域之外执行。

function createCounter() {
  let count = 0; // 这个变量被闭包"记住"了
  return {
    increment: () => ++count,
    getCount: () => count,
  };
}

const counter = createCounter();
counter.increment();
counter.increment();
console.log(counter.getCount()); // 2

应用场景:数据封装、函数工厂、模块模式

原型链

每个对象都有一个 __proto__ 指向其构造函数的 prototype:

function Person(name) {
  this.name = name;
}

Person.prototype.sayHello = function() {
  return `Hello, I'm ${this.name}`;
};

const p = new Person('Alice');
console.log(p.sayHello()); // "Hello, I'm Alice"

// 原型链查找过程
// p → Person.prototype → Object.prototype → null

Promise

// 手写 Promise.all 的简化版
function promiseAll(promises) {
  return new Promise((resolve, reject) => {
    const results = [];
    let completed = 0;

    promises.forEach((promise, index) => {
      Promise.resolve(promise).then(
        (value) => {
          results[index] = value;
          if (++completed === promises.length) {
            resolve(results);
          }
        },
        reject
      );
    });

    if (promises.length === 0) resolve(results);
  });
}

CSS 布局

Flex 居中

/* 最常用的居中方式 */
.flex-center {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* 或者使用 margin: auto */
.flex-center-alt {
  display: flex;
}
.flex-center-alt > * {
  margin: auto;
}

Grid 布局

/* 响应式网格 */
.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 1.5rem;
}

性能优化

防抖(Debounce)

function debounce(fn, delay) {
  let timer = null;
  return function(...args) {
    clearTimeout(timer);
    timer = setTimeout(() => fn.apply(this, args), delay);
  };
}

// 使用
const handleSearch = debounce((keyword) => {
  fetchResults(keyword);
}, 300);

节流(Throttle)

function throttle(fn, interval) {
  let lastTime = 0;
  return function(...args) {
    const now = Date.now();
    if (now - lastTime >= interval) {
      lastTime = now;
      fn.apply(this, args);
    }
  };
}

// 使用
window.addEventListener('scroll', throttle(handleScroll, 100));

Vue 相关

nextTick 原理

Vue 的 DOM 更新是异步的,nextTick 用于在 DOM 更新后执行操作:

import { nextTick } from 'vue';

async function updateAndRead() {
  message.value = '新消息';
  // 此时 DOM 还没更新
  await nextTick();
  // 现在 DOM 已更新
  console.log(document.getElementById('msg').textContent);
}

响应式原理

Vue 3 使用 Proxy 实现响应式:

// 简化版响应式实现
function reactive(target) {
  return new Proxy(target, {
    get(obj, key, receiver) {
      track(obj, key); // 收集依赖
      return Reflect.get(obj, key, receiver);
    },
    set(obj, key, value, receiver) {
      const result = Reflect.set(obj, key, value, receiver);
      trigger(obj, key); // 触发更新
      return result;
    },
  });
}

总结

面试准备的关键是理解原理而非死记硬背。当你能用代码解释一个概念时,才是真正掌握了它。