ES6+ 现代语法面试题
现代JavaScript语法是前端开发的基础,涵盖ES6到ES2024的新特性和最佳实践。
🔥 核心语法面试题
1. ES6+ 解构赋值和扩展运算符
问题:详细解释解构赋值的各种用法,以及扩展运算符在实际开发中的应用场景。
参考答案:
javascript
// 数组解构
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [3, 4, 5]
// 对象解构
const { name, age, address: { city } } = {
name: 'John',
age: 30,
address: { city: 'Beijing', country: 'China' }
};
// 函数参数解构
function processUser({ name, email, role = 'user' }) {
return { name, email, role };
}
// 扩展运算符 - 数组
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// 扩展运算符 - 对象
const user = { name: 'Alice', age: 25 };
const updatedUser = { ...user, role: 'admin', age: 26 };
// 函数调用中的扩展运算符
Math.max(...[1, 5, 3, 9, 2]); // 9
// 实际应用:深拷贝(浅层)
function shallowClone(obj) {
return Array.isArray(obj) ? [...obj] : { ...obj };
}
// 数组去重
const uniqueArray = [...new Set([1, 2, 2, 3, 3, 4])];应用场景:
- API响应数据提取
- 组件prop传递
- 状态更新(不可变数据)
- 函数参数简化
2. 箭头函数和this绑定
问题:箭头函数与普通函数的区别,特别是this指向和使用场景?
参考答案:
javascript
// 普通函数 vs 箭头函数
const obj = {
name: 'Test',
// 普通函数:动态this
regularMethod: function() {
console.log(this.name); // 'Test'
setTimeout(function() {
console.log(this.name); // undefined (在严格模式)
}, 100);
},
// 箭头函数:词法this
arrowMethod: function() {
console.log(this.name); // 'Test'
setTimeout(() => {
console.log(this.name); // 'Test'
}, 100);
}
};
// 不能作为构造函数
const ArrowConstructor = () => {};
// new ArrowConstructor(); // TypeError
// 没有arguments对象
function normalFunc() {
console.log(arguments); // Arguments对象
}
const arrowFunc = () => {
// console.log(arguments); // ReferenceError
};
// 实际应用:事件处理
class EventHandler {
constructor() {
this.count = 0;
}
// 箭头函数自动绑定this
handleClick = () => {
this.count++;
console.log(`Clicked ${this.count} times`);
}
// 需要手动绑定this
handleClickRegular() {
this.count++;
}
}
// React中的应用
class MyComponent extends React.Component {
state = { count: 0 };
// 自动绑定,无需在constructor中bind
increment = () => {
this.setState(prevState => ({ count: prevState.count + 1 }));
}
render() {
return <button onClick={this.increment}>Count: {this.state.count}</button>;
}
}3. Promise 和 async/await 深度理解
问题:详细解释Promise的工作原理,以及async/await的优势和错误处理。
参考答案:
javascript
// Promise基础
function createPromise(delay, shouldReject = false) {
return new Promise((resolve, reject) => {
setTimeout(() => {
if (shouldReject) {
reject(new Error(`Promise rejected after ${delay}ms`));
} else {
resolve(`Promise resolved after ${delay}ms`);
}
}, delay);
});
}
// Promise链式调用
createPromise(1000)
.then(result => {
console.log(result);
return createPromise(500);
})
.then(result => {
console.log(result);
})
.catch(error => {
console.error('Error:', error.message);
});
// Promise.all - 并行执行
async function parallelExecution() {
try {
const promises = [
createPromise(1000),
createPromise(2000),
createPromise(1500)
];
const results = await Promise.all(promises);
console.log('All resolved:', results);
} catch (error) {
console.error('One failed:', error.message);
}
}
// Promise.allSettled - 等待所有完成
async function allSettledExample() {
const promises = [
createPromise(1000),
createPromise(500, true), // 这个会reject
createPromise(1500)
];
const results = await Promise.allSettled(promises);
results.forEach((result, index) => {
if (result.status === 'fulfilled') {
console.log(`Promise ${index}: ${result.value}`);
} else {
console.error(`Promise ${index} failed: ${result.reason.message}`);
}
});
}
// async/await 错误处理
async function robustAsyncFunction() {
try {
// 串行执行
const result1 = await createPromise(1000);
const result2 = await createPromise(500);
return { result1, result2 };
} catch (error) {
console.error('Async function failed:', error.message);
throw error; // 重新抛出或处理
}
}
// 并发控制
async function concurrentWithLimit(urls, limit = 3) {
const results = [];
const executing = [];
for (const url of urls) {
const promise = fetch(url).then(response => response.json());
results.push(promise);
if (urls.length >= limit) {
executing.push(promise);
if (executing.length >= limit) {
await Promise.race(executing);
executing.splice(executing.findIndex(p => p === promise), 1);
}
}
}
return Promise.all(results);
}
// 自定义Promise工具
class PromiseUtils {
static timeout(promise, ms) {
return Promise.race([
promise,
new Promise((_, reject) =>
setTimeout(() => reject(new Error('Timeout')), ms)
)
]);
}
static retry(asyncFn, maxRetries = 3, delay = 1000) {
return new Promise(async (resolve, reject) => {
for (let i = 0; i <= maxRetries; i++) {
try {
const result = await asyncFn();
resolve(result);
return;
} catch (error) {
if (i === maxRetries) {
reject(error);
return;
}
await new Promise(r => setTimeout(r, delay));
}
}
});
}
}4. 模块系统 (ES Modules)
问题:ES Modules与CommonJS的区别,以及现代模块化开发的最佳实践?
参考答案:
javascript
// ES Modules 导出方式
// math.js
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export function multiply(a, b) {
return a * b;
}
// 默认导出
export default class Calculator {
add(a, b) { return a + b; }
subtract(a, b) { return a - b; }
}
// 重新导出
export { default as Calculator } from './calculator.js';
export * from './utilities.js';
// ES Modules 导入方式
// main.js
import Calculator, { add, multiply, PI } from './math.js';
import * as MathUtils from './math.js';
import { add as mathAdd } from './math.js'; // 重命名
// 动态导入
async function loadModule() {
const { add } = await import('./math.js');
return add(2, 3);
}
// 条件导入
if (process.env.NODE_ENV === 'development') {
const { debugUtils } = await import('./debug-utils.js');
}
// CommonJS vs ES Modules 对比
// CommonJS (Node.js)
const fs = require('fs');
const { readFile } = require('fs').promises;
module.exports = {
readConfig: () => { /* */ }
};
// ES Modules 优势:
// 1. 静态分析 - Tree Shaking
// 2. 异步加载
// 3. 更好的循环依赖处理
// 4. 浏览器原生支持
// 实际应用:模块聚合
// components/index.js
export { default as Button } from './Button.js';
export { default as Input } from './Input.js';
export { default as Modal } from './Modal.js';
// 使用聚合模块
import { Button, Input, Modal } from './components';
// Webpack代码分割
const LazyComponent = React.lazy(() => import('./LazyComponent'));
// 动态路由
const routes = [
{
path: '/users',
component: () => import('./pages/Users.vue')
}
];💡 高级语法特性
5. 生成器函数和迭代器
问题:解释Generator函数的工作原理和实际应用场景。
参考答案:
javascript
// 基础生成器
function* simpleGenerator() {
yield 1;
yield 2;
yield 3;
}
const gen = simpleGenerator();
console.log(gen.next()); // { value: 1, done: false }
console.log(gen.next()); // { value: 2, done: false }
// 实际应用:无限序列
function* fibonacciGenerator() {
let [prev, curr] = [0, 1];
while (true) {
yield curr;
[prev, curr] = [curr, prev + curr];
}
}
// 使用生成器
const fib = fibonacciGenerator();
for (let i = 0; i < 10; i++) {
console.log(fib.next().value);
}
// 异步生成器处理
async function* asyncDataGenerator() {
let page = 1;
while (true) {
const response = await fetch(`/api/data?page=${page}`);
const data = await response.json();
if (data.length === 0) break;
for (const item of data) {
yield item;
}
page++;
}
}
// 使用异步生成器
async function processData() {
for await (const item of asyncDataGenerator()) {
console.log('Processing:', item);
}
}
// 自定义迭代器
class Range {
constructor(start, end) {
this.start = start;
this.end = end;
}
*[Symbol.iterator]() {
for (let i = this.start; i <= this.end; i++) {
yield i;
}
}
}
const range = new Range(1, 5);
for (const num of range) {
console.log(num); // 1, 2, 3, 4, 5
}6. Proxy 和 Reflect
问题:Proxy对象的应用场景和与Reflect的配合使用?
参考答案:
javascript
// 基础 Proxy
const target = {
name: 'John',
age: 30
};
const proxy = new Proxy(target, {
get(obj, prop) {
console.log(`Getting ${prop}`);
return Reflect.get(obj, prop);
},
set(obj, prop, value) {
console.log(`Setting ${prop} to ${value}`);
return Reflect.set(obj, prop, value);
}
});
// 实际应用:数据验证
function createValidatedObject(target, validators) {
return new Proxy(target, {
set(obj, prop, value) {
if (validators[prop]) {
if (!validators[prop](value)) {
throw new Error(`Invalid value for ${prop}`);
}
}
return Reflect.set(obj, prop, value);
}
});
}
const user = createValidatedObject({}, {
email: value => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
age: value => typeof value === 'number' && value >= 0
});
// Vue 3 响应式系统简化版
function reactive(target) {
const handlers = {
get(obj, prop, receiver) {
// 依赖收集
track(obj, prop);
return Reflect.get(obj, prop, receiver);
},
set(obj, prop, value, receiver) {
const result = Reflect.set(obj, prop, value, receiver);
// 触发更新
trigger(obj, prop);
return result;
}
};
return new Proxy(target, handlers);
}
// API 代理
const api = new Proxy({}, {
get(target, prop) {
return async (...args) => {
const response = await fetch(`/api/${prop}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(args)
});
return response.json();
};
}
});
// 使用:api.getUser(123) -> POST /api/getUser
const userData = await api.getUser(123);这些ES6+现代语法面试题涵盖了JavaScript的核心特性和实际应用,展示了对现代Web开发技术栈的深入理解。
