1. JavaScript 中的微任务(Microtask)和宏任务(Macrotask)
宏任务(Macrotask)
宏任务代表较大的、离散的工作单元,由 事件循环机制 处理,每次事件循环会执行一个宏任务。
常见的宏任务包括:
setTimeout/setInterval- 定时器回调setImmediate- Node.js特有,在当前事件循环的检查(check)阶段执行- I/O 操作 - 文件读写、网络请求等异步操作的回调
- UI 渲染 - 浏览器重绘/重排
- 事件回调 - DOM事件、鼠标键盘事件等
requestAnimationFrame- 浏览器动画回调MessageChannel- 消息通道通信
微任务(Microtask)
微任务是在当前宏任务执行完成后、下一个宏任务开始前立即执行的任务,它们有更高的优先级。
常见的微任务包括:
Promise.then()/Promise.catch()/Promise.finally()- Promise回调queueMicrotask()- 显式添加微任务MutationObserver- DOM变动观察器process.nextTick- Node.js特有,比微任务优先级更高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
事件循环中的执行顺序
- 执行一个宏任务(如script整体代码)
- 执行所有微任务
- 如有必要,渲染UI
- 从宏任务队列中取出下一个任务执行
为什么区分微任务和宏任务重要?
- 性能优化:微任务可以更快执行,避免不必要的UI渲染
- 执行顺序控制:理解执行顺序可以避免竞态条件
- 避免阻塞:合理分配任务类型可以防止主线程阻塞
理解微任务和宏任务的机制对于编写高效、可预测的异步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 取代。