十二月 21, 2025
36 分钟阅读

初级前端开发面试题:HTML、CSS和JavaScript基础

interview
career-advice
job-search
entry-level
初级前端开发面试题:HTML、CSS和JavaScript基础
MB

Milad Bonakdar

作者

掌握核心基础知识:32个涵盖HTML、CSS和JavaScript的必备面试题。为2024-2025年的初级前端开发面试做好充分准备。


前言

本综合指南包含 32 个精心挑选的面试问题,涵盖了前端开发的核心基础知识:HTML、CSS 和 JavaScript。 这些问题是初级前端开发人员在 2024-2025 年的面试中实际遇到的问题。 每个问题都包括透彻的答案、稀有度评估和难度等级,这些都基于对来自主要科技公司和初创公司的数百次真实面试的分析。

这是我们完整面试指南的第 1 部分。 有关 React、构建工具、性能优化、调试、可访问性、测试和软技能的问题,请查看第 2 部分:React、工具和高级主题


HTML 基础 (7 个问题)

1. 什么是语义化 HTML 元素? 为什么它们很重要?

回答: 语义化 HTML 元素清楚地向浏览器和开发人员描述了它们的含义和目的。 示例包括 <header><nav><main><article><section><aside><footer>。 它们之所以重要,是因为它们提高了屏幕阅读器和辅助技术的可访问性,通过帮助搜索引擎理解内容结构来增强 SEO,并使代码更易于维护和阅读。 与不提供任何上下文的通用 <div><span> 元素不同,语义元素传达了内容的角色和含义。

稀有度: 常见 难度: 简单


2. 解释行内元素、块级元素和行内块级元素之间的区别

回答:

  • 块级元素 从新行开始,并占用可用空间的全部宽度(例如,<div><p><h1>)。 您可以设置 width 和 height 属性。
  • 行内元素 保持在同一行,并且仅占用所需的宽度(例如,<span><a><strong>)。 您无法设置 width 或 height。
  • 行内块级元素 保持在同一行,但允许您像块级元素一样设置 width 和 height。 这结合了行内元素的流动性和块级元素的尺寸调整功能。

稀有度: 常见 难度: 简单


3. 什么是 HTML 中的空(自闭合)元素?

回答: 空元素是不具有闭合标签并且不能包含内容的 HTML 元素。 常见的示例包括:<img><br><hr><input><meta><link><area><base><col><embed><source>。 这些元素仅包含其开始标记和属性。 例如,<img src="photo.jpg" alt="description"> 不需要闭合 </img> 标签。

稀有度: 常见 难度: 简单


4. 如何使网站具有可访问性? 哪些 HTML 属性可以提高可访问性?

回答: 为了使网站具有可访问性:

  • 使用语义化 HTML 元素(<nav><main><header><footer>
  • 为所有描述其内容的图像提供 alt 属性
  • 维护正确的标题层次结构 (H1-H6),不要跳过级别
  • 使用 for 属性使用 <label> 元素标记表单输入
  • 通过正确的制表符顺序确保键盘可访问性
  • 在语义化 HTML 不足时使用 ARIA 属性:aria-labelaria-describedbyaria-hiddenaria-live
  • 为复杂的窗口小部件添加 role 属性
  • 确保足够的颜色对比度(正常文本为 4.5:1)
  • 使交互式元素可聚焦并提供可见的焦点指示器

稀有度: 常见 难度: 中等


5. 解释表单中 GET 和 POST 方法之间的区别

回答:

  • GET: 将表单数据作为查询参数附加到 URL,使数据在浏览器中可见。 具有长度限制(约 2000 个字符),可以缓存和添加书签,对于敏感数据不安全。 用于检索数据,其中请求不修改服务器状态(搜索、过滤器)。
  • POST: 在请求正文中发送数据,在 URL 中不可见。 没有长度限制,默认情况下不能缓存,对于敏感信息更安全。 用于提交修改服务器状态的数据(登录表单、文件上传、创建记录)。

示例:搜索表单通常使用 GET,以便可以为结果添加书签,而登录表单使用 POST 来隐藏凭据。

稀有度: 常见 难度: 简单-中等


6. <meta> 标签的目的是什么?

回答: <meta> 标签提供有关 HTML 文档的元数据,这些元数据不会显示在页面上,但会被浏览器、搜索引擎和其他 Web 服务使用。 常见的用途包括:

  • 字符编码:<meta charset="UTF-8">
  • 用于响应式设计的视口设置:<meta name="viewport" content="width=device-width, initial-scale=1.0">
  • SEO 描述:<meta name="description" content="页面描述">
  • 作者信息:<meta name="author" content="姓名">
  • 关键字(现在不太相关):<meta name="keywords" content="关键字 1, 关键字 2">

稀有度: 常见 难度: 简单


7. <script><script async><script defer> 之间有什么区别?

回答:

  • 常规 <script> 在脚本下载和执行时阻止 HTML 解析。 页面渲染会停止,直到脚本完成。
  • <script async> 与 HTML 解析并行下载脚本,但在准备就绪时立即执行(可能会阻止解析)。 执行顺序不能保证。 适用于独立的脚本,如分析。
  • <script defer> 并行下载,但在 HTML 解析完成后才执行,从而保持脚本顺序。 最适合依赖于 DOM 或其他脚本的脚本。

最佳实践:将 <script defer> 放置在 <head> 中,以获得最佳性能,同时确保正确的执行顺序。

稀有度: 不常见 难度: 中等


CSS 基础 (10 个问题)

8. 解释 CSS 盒模型

回答: CSS 盒模型描述了如何使用四个组件(从内到外)渲染元素:

  1. 内容: 实际内容(文本、图像)
  2. 内边距: 内容和边框之间的空间(内部)
  3. 边框: 围绕内边距的边框
  4. 外边距: 边框外部的空间(元素之间)

box-sizing 属性会影响计算:

  • box-sizing: content-box(默认):Width/height 仅适用于内容;添加内边距和边框
  • box-sizing: border-box:Width/height 包括内容 + 内边距 + 边框(更直观)

示例:使用 box-sizing: border-box,具有 width: 100px; padding: 10px; border: 2px; 的元素保持完全 100px 宽。

稀有度: 常见 难度: 简单-中等


9. 解释 CSS 特性以及它的工作原理

回答: CSS 特性决定了当多个规则针对同一元素时应用哪些样式。 特性是通过计算选择器来计算的:

  • 内联样式: 1000 点
  • ID: 每个 100 点
  • 类、属性、伪类: 每个 10 点
  • 元素、伪元素: 每个 1 点

示例:

  • #nav .button = 110(1 个 ID + 1 个类)
  • .header .nav a = 21(2 个类 + 1 个元素)
  • div p = 2(2 个元素)

当特性相等时,最后一个规则获胜(层叠)。 !important 覆盖所有内容,但应避免使用。 最佳实践:使用类进行样式设置,避免使用 ID 和 !important。

稀有度: 常见 难度: 中等


10. 什么是 Flexbox?何时使用它?

回答: Flexbox 是一种一维布局系统,用于沿单个轴(行或列)排列项目。

父级(flex 容器)属性:

  • display: flex - 启用 flexbox
  • flex-direction - row, column, row-reverse, column-reverse
  • justify-content - 沿主轴对齐(center、space-between、space-around)
  • align-items - 沿交叉轴对齐(center、flex-start、flex-end、stretch)
  • flex-wrap - 控制换行(nowrap、wrap)

子级(flex 项目)属性:

  • flex-grow - 项目相对于其他项目增长多少
  • flex-shrink - 项目收缩多少
  • flex-basis - 增长/收缩之前的初始大小
  • align-self - 覆盖单个项目的 align-items

使用 Flexbox 的情况: 导航栏、卡片布局、居中元素、均匀分配空间、在容器内对齐项目。

稀有度: 常见 难度: 中等


11. 什么是 CSS Grid?它与 Flexbox 有何不同?

回答: CSS Grid 是一种二维布局系统,用于同时创建具有行和列的复杂布局。

主要区别:

  • Grid: 二维(行 + 列),最适合页面布局
  • Flexbox: 一维(单轴),最适合组件

Grid 属性:

.container {
  display: grid;
  grid-template-columns: 1fr 2fr 1fr; /* 3 列 */
  grid-template-rows: 100px auto 50px;
  grid-gap: 20px; /* 或 gap */
}

何时使用:

  • Grid: 整体页面布局、杂志式设计、复杂的网格结构
  • Flexbox: 导航栏、卡片、网格单元格中的组件
  • 两者结合: Grid 用于宏观布局,Flexbox 用于微观布局

稀有度: 常见 难度: 中等


12. 如何水平和垂直居中 div?

回答:

现代方法(首选):

/* Flexbox */
.parent {
  display: flex;
  justify-content: center;
  align-items: center;
}

/* Grid */
.parent {
  display: grid;
  place-items: center;
}

旧方法:

/* 绝对定位 */
.child {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

/* Margin auto(仅水平,需要宽度) */
.child {
  margin: 0 auto;
  width: 300px;
}

Flexbox 和 Grid 现在是标准解决方案,因为它们更简洁且更灵活。

稀有度: 常见 难度: 简单-中等


13. 解释 CSS 定位:static、relative、absolute、fixed 和 sticky

回答:

  • Static(默认): 正常的文档流,没有特殊的定位
  • Relative: 使用 top/right/bottom/left 相对于其正常位置进行定位。 保留文档流中的原始空间。 通常用作绝对子元素的定位上下文。
  • Absolute: 从流中移除,相对于最近的已定位祖先(如果没有,则相对于视口)进行定位。 不会影响其他元素。
  • Fixed: 从流中移除,相对于视口进行定位。 滚动时保持在原位。
  • Sticky: relative 和 fixed 的混合。 在滚动阈值之前充当 relative,然后变为 fixed。 对于以流入方式开始的粘性标题很有用。

示例:在滚动后变为固定的导航使用 position: sticky; top: 0;

稀有度: 常见 难度: 中等


14. display: nonevisibility: hiddenopacity: 0 之间有什么区别?

回答:

  • display: none 元素完全从文档流中移除,不占用空间,屏幕阅读器无法访问,没有指针事件
  • visibility: hidden 元素不可见,但保持布局中的空间,仍在 DOM 中,屏幕阅读器无法访问,没有指针事件
  • opacity: 0 元素不可见,但保持空间,仍在 DOM 中,屏幕阅读器仍然可以访问,仍然接收指针事件

用例:

  • display: none - 切换可见性(模态框、下拉菜单)
  • visibility: hidden - 在隐藏时保持布局
  • opacity: 0 - 淡入淡出动画,保持元素的交互性

稀有度: 常见 难度: 简单-中等


15. 什么是 CSS 伪类和伪元素? 提供示例。

回答:

伪类(单冒号) - 根据状态或位置选择元素:

a:hover { color: blue; }          /* 鼠标悬停 */
input:focus { border: 2px solid blue; }  /* 键盘焦点 */
li:nth-child(odd) { background: #eee; }  /* 奇数列表项 */
button:disabled { opacity: 0.5; }  /* 禁用状态 */

其他示例::active:checked:first-child:last-child:nth-of-type()

伪元素(双冒号) - 设置特定部分的样式或插入内容:

p::first-line { font-weight: bold; }  /* 段落的第一行 */
p::first-letter { font-size: 2em; }   /* 首字下沉 */
.icon::before { content: "→"; }        /* 插入内容 */
input::placeholder { color: gray; }    /* 占位符文本 */

伪元素非常适合在不添加 HTML 的情况下进行装饰性元素。

稀有度: 常见 难度: 中等


16. 如何创建响应式布局? 解释媒体查询。

回答: 响应式布局使用以下方式适应不同的屏幕尺寸:

媒体查询:

/* 移动优先方法(推荐) */
.container { width: 100%; }

@media screen and (min-width: 768px) {
  .container { width: 750px; }  /* 平板电脑 */
}

@media screen and (min-width: 1024px) {
  .container { width: 960px; }  /* 桌面 */
}

常用断点:

  • 320px:小型手机
  • 768px:平板电脑
  • 1024px:桌面
  • 1440px:大型桌面

其他响应式技术:

  • 流式布局(百分比、vw/vh 单位)
  • 灵活的 Flexbox 和 Grid
  • 响应式图像(max-width: 100%srcset 属性)
  • min-width 查询(移动优先)与 max-width(桌面优先)

稀有度: 常见 难度: 中等


17. 什么是 z-index?它的工作原理是什么?

回答: z-index 控制沿 z 轴(从前到后)定位的元素(relative、absolute、fixed、sticky)的堆叠顺序。

要点:

  • 仅适用于已定位的元素(非 static)
  • 较高的值出现在前面
  • 可以使用负值
  • 默认值为 auto(实际上为 0)
  • 创建一个“堆叠上下文”,它会影响子元素的堆叠方式

常见的陷阱:

.parent { position: relative; z-index: 1; }
.child { position: absolute; z-index: 9999; }

z-index 为 9999 的子元素不能出现在 z-index 为 2 且位于父级堆叠上下文之外的另一个元素之上。

稀有度: 常见 难度: 中等


JavaScript 基础 (15 个问题)

18. 解释 varletconst 之间的区别

回答:

  • var 函数作用域,提升并使用 undefined 初始化,可以重新声明,在现代代码中已基本弃用
  • let 块作用域,提升但在声明之前位于暂时性死区 (TDZ) 中,不能在同一作用域中重新声明
  • const 块作用域,提升但在 TDZ 中,必须在声明时初始化,不能重新赋值(但对象/数组内容可以改变)

最佳实践:

  • 默认使用 const
  • 需要重新赋值时使用 let
  • 在现代 JavaScript 中永远不要使用 var

示例:

const name = "Alice";     // 无法重新赋值
let count = 0;            // 可以重新赋值
count = 1;                // 确定
name = "Bob";             // 错误!

const user = { age: 25 };
user.age = 26;            // 确定 - 改变对象属性
user = {};                // 错误 - 重新赋值

稀有度: 常见 难度: 简单


19. 什么是闭包?提供一个实际示例?

回答: 闭包是指内部函数可以访问其外部(封闭)函数作用域中的变量,即使在外部函数返回后也是如此。 内部函数“关闭”这些变量。

示例:

function createCounter() {
  let count = 0;  // 私有变量
  
  return function() {
    count++;
    return count;
  };
}

const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2
console.log(counter()); // 3

内部函数保持对 count 的访问权限,即使 createCounter 已完成执行。 这样可以实现数据隐私 - 无法从外部直接访问 count

用例: 数据隐私、函数工厂、回调、模块模式、事件处理程序

稀有度: 常见 难度: 中等


20. 解释 JavaScript 中的 =====

回答:

  • ==(松散相等): 在比较之前执行类型强制转换,转换类型以匹配
  • ===(严格相等): 检查值和类型,不进行类型强制转换

示例:

5 == '5'       // true(字符串强制转换为数字)
5 === '5'      // false(不同类型)

null == undefined   // true(特殊情况)
null === undefined  // false(不同类型)

0 == false     // true(都强制转换)
0 === false    // false(数字与布尔值)

最佳实践: 始终使用 ===!==,以避免类型强制转换导致的意外错误。

稀有度: 常见 难度: 简单


21. 什么是 JavaScript 中的提升?

回答: 提升是 JavaScript 在编译阶段将变量和函数声明移动到其作用域顶部的行为,在代码执行之前。

不同的提升行为:

console.log(x);  // undefined(已提升,已初始化)
var x = 5;

console.log(y);  // ReferenceError(已提升但在 TDZ 中)
let y = 5;

sayHello();      // "Hello!"(函数完全提升)
function sayHello() {
  console.log("Hello!");
}

sayHi();         // TypeError(不是函数)
var sayHi = function() {
  console.log("Hi!");
};

要点:

  • var 声明被提升并使用 undefined 初始化
  • let/const 被提升但保持未初始化状态(暂时性死区)
  • 函数声明被完全提升(包括实现)
  • 函数表达式未完全提升

稀有度: 常见 难度: 中等


22. 解释 this 关键字以及它在箭头函数中的不同之处

回答: this 指的是函数执行的上下文。 它的值取决于如何调用函数。

常规函数:

const obj = {
  name: "John",
  greet: function() {
    console.log(this.name);  // "John"
  }
};
obj.greet();  // this = obj

const greet = obj.greet;
greet();  // this = undefined(严格模式)或 window

箭头函数:

const obj = {
  name: "John",
  greet: () => {
    console.log(this.name);  // undefined
  }
};
obj.greet();  // this = 词法作用域(封闭上下文)

主要区别:

  • 常规函数:this 由调用站点确定
  • 箭头函数:this 从封闭作用域词法继承
  • 箭头函数没有自己的 thisargumentssuper

用例: 箭头函数非常适合要保留外部 this 的回调:

class Timer {
  start() {
    setTimeout(() => {
      console.log(this);  // Timer 实例(词法)
    }, 1000);
  }
}

稀有度: 常见 难度: 中等-困难


23. 什么是模板字面量?它们有什么好处?

回答: 模板字面量是使用反引号 (`) 的字符串字面量,支持字符串插值和多行字符串。

特点:

const name = "Alice";
const age = 25;

// 字符串插值
const message = `Hello, my name is ${name} and I'm ${age} years old.`;

// 多行字符串
const html = `
  <div>
    <h1>${title}</h1>
    <p>${content}</p>
  </div>
`;

// 表达式求值
const price = `Total: $${(quantity * unitPrice).toFixed(2)}`;

好处:

  • 比字符串连接更简洁的语法
  • 无需 \n 进行换行
  • 可以使用 ${} 嵌入任何 JavaScript 表达式
  • 更适合 HTML/CSS 生成

稀有度: 常见 难度: 简单


24. 解释 Promise 及其三种状态

回答: Promise 表示异步操作及其结果值的最终完成(或失败)。

三种状态:

  1. Pending: 初始状态,操作未完成
  2. Fulfilled: 操作成功完成
  3. Rejected: 操作失败

示例:

const fetchData = new Promise((resolve, reject) => {
  setTimeout(() => {
    const success = true;
    if (success) {
      resolve({ data: "User info" });
    } else {
      reject(new Error("Failed to fetch"));
    }
  }, 1000);
});

fetchData
  .then(result => console.log(result))
  .catch(error => console.error(error))
  .finally(() => console.log("Done"));

优于回调的好处:

  • 避免回调地狱
  • 可以使用 .then() 链接
  • 使用 .catch() 更好地处理错误
  • 可以使用 Promise.all() 进行并行操作

稀有度: 常见 难度: 中等


25. 什么是 async/await?它如何提高代码可读性?

回答: async/await 是建立在 Promise 之上的语法糖,使异步代码看起来和行为更像同步代码。

示例:

// 使用 Promise(更难阅读)
function fetchUserData() {
  return fetch('/api/user')
    .then(response => response.json())
    .then(data => {
      return fetch(`/api/posts/${data.id}`);
    })
    .then(response => response.json())
    .catch(error => console.error(error));
}

// 使用 async/await(更简洁)
async function fetchUserData() {
  try {
    const response = await fetch('/api/user');
    const user = await response.json();
    
    const postsResponse = await fetch(`/api/posts/${user.id}`);
    const posts = await postsResponse.json();
    
    return posts;
  } catch (error) {
    console.error(error);
  }
}

要点:

  • async 函数始终返回 Promise
  • await 暂停执行直到 Promise 解决
  • 使用 try/catch 处理错误
  • 使顺序操作更清晰
  • 错误处理比 .catch() 更自然

稀有度: 常见 难度: 中等


26. 解释事件循环以及 JavaScript 如何处理异步操作

回答: JavaScript 是单线程的,但通过事件循环机制处理异步操作。

组件:

  1. 调用堆栈: 执行同步代码 (LIFO)
  2. Web API: 处理异步操作(setTimeout、fetch、DOM 事件)
  3. 回调队列(任务队列): 保存来自 Web API 的回调
  4. 微任务队列: 保存 Promise 回调(优先级更高)
  5. 事件循环: 当堆栈为空时,将任务从队列移动到调用堆栈

执行顺序:

console.log('1');

setTimeout(() => console.log('2'), 0);

Promise.resolve().then(() => console.log('3'));

console.log('4');

// 输出:1, 4, 3, 2
// 说明:
// - 首先运行同步代码 (1, 4)
// - 微任务(Promise)在宏任务之前运行
// - 宏任务 (setTimeout) 最后运行

执行顺序: 调用堆栈 → 微任务队列 → 回调队列(宏任务)

稀有度: 常见 难度: 困难


27. 如何选择和操作 DOM 元素?

回答:

选择方法:

// 现代(首选)
const element = document.querySelector('#myId');
const elements = document.querySelectorAll('.myClass');
const firstItem = document.querySelector('.list-item');

// 旧版(仍然有效)
const elem = document.getElementById('myId');
const elems = document.getElementsByClassName('myClass');
const tags = document.getElementsByTagName('div');

操作:

// 内容
element.textContent = 'New text';
element.innerHTML = '<span>HTML content</span>';

// 样式
element.style.color = 'blue';
element.style.backgroundColor = '#eee';

// 类
element.classList.add('active');
element.classList.remove('hidden');
element.classList.toggle('visible');
element.classList.contains('active');

// 属性
element.setAttribute('data-id', '123');
element.getAttribute('data-id');

// 创建元素
const newDiv = document.createElement('div');
newDiv.textContent = 'Hello';
document.body.appendChild(newDiv);

稀有度: 常见 难度: 简单


28. 解释事件委托以及它为什么有用

回答: 事件委托是将单个事件侦听器附加到父元素,而不是将多个侦听器附加到子元素,从而利用事件冒泡。

没有委托(效率低):

document.querySelectorAll('.item').forEach(item => {
  item.addEventListener('click', handleClick);
});

使用委托(效率高):

document.getElementById('list').addEventListener('click', (e) => {
  if (e.target.matches('.item')) {
    handleClick(e);
  }
});

好处:

  • 更好的性能: 单个侦听器与多个侦听器
  • 适用于动态元素: 自动处理以后添加的项目
  • 更低的内存使用量: 更少的事件侦听器
  • 更简洁的代码: 集中式事件处理

用例: 可以动态添加/删除项目的列表(待办事项列表、购物车、评论部分)

稀有度: 常见 难度: 中等


29. 什么是事件冒泡?如何停止传播?

回答: 事件冒泡是指在子元素上触发的事件通过其祖先“冒泡”到文档根。

三个阶段:

  1. 捕获阶段: 事件从窗口向下传播到目标
  2. 目标阶段: 事件到达目标元素
  3. 冒泡阶段: 事件从目标向上冒泡到窗口(默认)

示例:

<div id="parent">
  <button id="child">Click me</button>
</div>

<script>
document.getElementById('parent').addEventListener('click', () => {
  console.log('Parent clicked');
});

document.getElementById('child').addEventListener('click', (e) => {
  console.log('Child clicked');
  // 事件冒泡到父级
});
// 单击按钮会记录:“Child clicked”,然后是“Parent clicked”
</script>

停止传播:

element.addEventListener('click', (e) => {
  e.stopPropagation();  // 停止冒泡
  e.preventDefault();    // 阻止默认行为(表单提交、链接导航)
});

稀有度: 常见 难度: 中等


30. 解释对象和数组的解构

回答: 解构将值从数组或属性从对象提取到不同的变量中。

数组解构:

const colors = ['red', 'green', 'blue', 'yellow'];

const [first, second, ...rest] = colors;
// first = 'red'
// second = 'green'
// rest = ['blue', 'yellow']

// 跳过元素
const [primary, , tertiary] = colors;
// primary = 'red', tertiary = 'blue'

对象解构:

const user = {
  name: 'Alice',
  age: 25,
  email: '[email protected]'
};

const { name, age, city = 'NYC' } = user;
// name = 'Alice'
// age = 25
// city = 'NYC'(默认值)

// 重命名变量
const { name: userName, age: userAge } = user;

// 嵌套解构
const { address: { street, zip } } = person;

函数参数:

function greet({ name, age = 18 }) {
  console.log(`Hello ${name}, age ${age}`);
}

greet({ name: 'Bob', age: 25 });

稀有度: 常见 难度: 简单-中等


31. 解释展开运算符和剩余参数

回答:

展开运算符 (...) - 展开可迭代对象:

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

// 对象(浅拷贝)
const user = { name: 'Alice', age: 25 };
const updatedUser = { ...user, age: 26 };  // 不可变更新

// 函数参数
const numbers = [1, 2, 3];
Math.max(...numbers);  // 3

剩余参数 (...) - 收集多个元素:

// 函数参数
function sum(...numbers) {
  return numbers.reduce((a, b) => a + b, 0);
}
sum(1, 2, 3, 4);  // 10

// 数组解构
const [first, ...remaining] = [1, 2, 3, 4];
// first = 1, remaining = [2, 3, 4]

// 对象解构
const { name, ...otherProps } = user;

主要区别: 展开展开,剩余收集

稀有度: 常见 难度: 简单-中等


32. 什么是常见的数组方法?何时使用每种方法?

回答:

转换方法:

// map - 转换每个元素,返回新数组
const doubled = [1, 2, 3].map(x => x * 2);  // [2, 4, 6]

// filter - 保留匹配条件的元素
const evens = [1, 2, 3, 4].filter(x => x % 2 === 0);  // [2, 4]

// reduce - 减少为单个值
const sum = [1, 2, 3].reduce((acc, val) => acc + val, 0);  // 6

搜索方法:

// find - 匹配条件的第一个元素
const found = users.find(user => user.id === 5);

// findIndex - 第一个匹配项的索引
const index = arr.findIndex(x => x > 10);

// includes - 检查值是否存在
const hasValue = arr.includes(5);  // true/false

测试方法:

// some - 至少一个元素匹配
const hasEven = [1, 3, 5, 6].some(x => x % 2 === 0);  // true

// every - 所有元素都匹配
const allPositive = [1, 2, 3].every(x => x > 0);  // true

副作用(没有有用的返回值):

// forEach - 迭代而不返回新数组
arr.forEach(item => console.log(item));

稀有度: 常见 难度: 简单-中等

Newsletter subscription

真正有效的每周职业建议

将最新见解直接发送到您的收件箱

Decorative doodle

您的下一次面试只差一份简历

在几分钟内创建一份专业、优化的简历。无需设计技能——只有经过验证的结果。

创建我的简历

分享这篇文章

让您的6秒钟发挥作用

招聘人员平均只花6到7秒扫描简历。我们经过验证的模板旨在立即吸引注意力并让他们继续阅读。