前端高频面试题(React)

93 阅读4分钟

1. JavaScript 中的微任务(Microtask)和宏任务(Macrotask)

宏任务(Macrotask)

宏任务代表较大的、离散的工作单元,由 事件循环机制 处理,每次事件循环会执行一个宏任务。

常见的宏任务包括:

  1. setTimeout / setInterval - 定时器回调
  2. setImmediate - Node.js特有,在当前事件循环的检查(check)阶段执行
  3. I/O 操作 - 文件读写、网络请求等异步操作的回调
  4. UI 渲染 - 浏览器重绘/重排
  5. 事件回调 - DOM事件、鼠标键盘事件等
  6. requestAnimationFrame - 浏览器动画回调
  7. MessageChannel - 消息通道通信

微任务(Microtask)

微任务是在当前宏任务执行完成后、下一个宏任务开始前立即执行的任务,它们有更高的优先级。

常见的微任务包括:

  1. Promise.then() / Promise.catch() / Promise.finally() - Promise回调
  2. queueMicrotask() - 显式添加微任务
  3. MutationObserver - DOM变动观察器
  4. process.nextTick - Node.js特有,比微任务优先级更高
  5. Object.observe (已废弃) - 对象变化观察

执行顺序示例

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

Node.js 中的特殊顺序

在Node.js中,process.nextTick 比微任务优先级更高:

Promise.resolve().then(() => console.log('promise'));
process.nextTick(() => console.log('nextTick'));

// 输出顺序:
// nextTick
// promise

事件循环中的执行顺序

  1. 执行一个宏任务(如script整体代码)
  2. 执行所有微任务
  3. 如有必要,渲染UI
  4. 从宏任务队列中取出下一个任务执行

为什么区分微任务和宏任务重要?

  1. 性能优化:微任务可以更快执行,避免不必要的UI渲染
  2. 执行顺序控制:理解执行顺序可以避免竞态条件
  3. 避免阻塞:合理分配任务类型可以防止主线程阻塞

理解微任务和宏任务的机制对于编写高效、可预测的异步JavaScript代码至关重要。


2. JavaScript 中的语法糖

语法糖(Syntactic Sugar)是指那些使代码更易读、更简洁的语法特性,它们不会引入新功能,只是提供更便捷的写法。以下是 JavaScript 中常见的语法糖:

1. 解构赋值 (Destructuring Assignment)

// 数组解构
const [a, b] = [1, 2]; // a=1, b=2

// 对象解构
const {name, age} = {name: 'Alice', age: 25};

2. 展开运算符 (Spread Operator)

// 数组展开
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]

// 对象展开
const obj1 = {a: 1};
const obj2 = {...obj1, b: 2}; // {a: 1, b: 2}

3. 箭头函数 (Arrow Functions)

// 传统函数
function add(a, b) { return a + b; }

// 箭头函数语法糖
const add = (a, b) => a + b;

4. 简写属性 (Property Shorthand)

const name = 'Alice';
const age = 25;

// 传统写法
const person = {name: name, age: age};

// 简写属性
const person = {name, age};

5. 模板字符串 (Template Literals)

const name = 'Alice';

// 传统字符串拼接
console.log('Hello, ' + name + '!');

// 模板字符串语法糖
console.log(`Hello, ${name}!`);

6. 可选链操作符 (Optional Chaining)

const user = { address: { city: 'New York' } };

// 传统写法
const city = user && user.address && user.address.city;

// 可选链语法糖
const city = user?.address?.city;

7. 空值合并运算符 (Nullish Coalescing)

const input = null;

// 传统写法
const value = input !== null && input !== undefined ? input : 'default';

// 空值合并语法糖
const value = input ?? 'default';

8. 类语法 (Class Syntax)

// 传统原型写法
function Person(name) {
  this.name = name;
}
Person.prototype.sayHello = function() {
  console.log('Hello, ' + this.name);
};

// 类语法糖
class Person {
  constructor(name) {
    this.name = name;
  }
  
  sayHello() {
    console.log(`Hello, ${this.name}`);
  }
}

9. 方法简写 (Method Shorthand)

const obj = {
  // 传统写法
  sayHello: function() { /* ... */ },
  
  // 方法简写语法糖
  sayHello() { /* ... */ }
};

10. 默认参数 (Default Parameters)

// 传统写法
function greet(name) {
  name = name || 'Guest';
  console.log('Hello, ' + name);
}

// 默认参数语法糖
function greet(name = 'Guest') {
  console.log(`Hello, ${name}`);
}

11. 指数运算符 (Exponentiation Operator)

// 传统写法
Math.pow(2, 3); // 8

// 指数运算符语法糖
2 ** 3; // 8

12. Array.includes() (替代 indexOf 检查)

const arr = [1, 2, 3];

// 传统写法
if (arr.indexOf(2) !== -1) { /* ... */ }

// includes语法糖
if (arr.includes(2)) { /* ... */ }

这些语法糖使 JavaScript 代码更简洁、更易读,但本质上它们只是底层功能的简化表达方式。理解这些语法糖背后的原理对于深入掌握 JavaScript 非常重要。

在 CSS 中,实现 div水平垂直居中有多种方法,适用于不同场景。以下是常见的几种方案:


3. div 水平垂直居中

方法 1:Flexbox 布局(推荐)

.container {
  display: flex;
  justify-content: center; /* 水平居中 */
  align-items: center;     /* 垂直居中 */
  height: 100vh;           /* 容器高度需明确 */
}

优点:代码简洁,现代浏览器广泛支持。
适用场景:全屏居中或任意尺寸容器。


方法 2:Grid 布局

.container {
  display: grid;
  place-items: center; /* 同时水平垂直居中 */
  height: 100vh;
}

优点:比 Flexbox 更简洁,适合现代布局。


方法 3:绝对定位 + Transform

.container {
  position: relative;
  height: 100vh;
}
.center-div {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%); /* 通过自身宽高反向偏移 */
}

优点:兼容性好(支持 IE9+),不依赖父容器尺寸。
适用场景:未知宽高的元素居中。


方法 4:绝对定位 + Margin Auto

.center-div {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  margin: auto;
  width: 100px;  /* 需明确宽高 */
  height: 100px;
}

注意:必须指定子元素的宽高。


方法 5:Table-Cell(传统方案)

.container {
  display: table-cell;
  vertical-align: middle; /* 垂直居中 */
  text-align: center;     /* 水平居中 */
  width: 100vw;
  height: 100vh;
}
.center-div {
  display: inline-block; /* 行内块元素响应水平居中 */
}

缺点:需嵌套多层标签,逐渐被 Flex/Grid 取代。