Skip to content

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开发技术栈的深入理解。

正在精进