2025前端面试题-JavaScript基础篇

以下为JavaScript基础篇面试考察点总结,具体知识点不会太详细,主要梳理面试核心考察点,为面试做准备。掌握这些基础知识,不仅是完成日常工作的基本要求,更是未来向中高级发展的基石。

一、 数据类型与内存机制

1. 基本数据类型

  • String
  • Number
  • Boolean
  • Null
  • Undefined
  • Symbol (ES6)
  • BigInt (ES2020)

特点

  • 存储在 栈内存 (Stack) 中;
  • 当一个变量被赋值为基本类型时,它直接持有该值;
  • 变量之间的赋值是值的复制。

2. 引用数据类型

主要是 : Object (包括普通对象、ArrayFunctionDate等)。

特点

  • 值本身(即对象实体)存储在堆内存 (Heap)中,而变量的值是指向该堆内存地址的引用 ,该引用存储在栈内存中;
  • 变量之间的赋值是引用的复制。

面试题代码示例

示例1: 基本类型赋值
js 复制代码
let a = 10;
let b = a;
b = 20;
console.log(a); // 输出什么?
// 解析: a 的值仍然是 10。因为 b = a 是值的复制,后续对 b 的修改不影响 a。
示例2: 引用类型赋值
js 复制代码
let obj1 = { name: 'Mickey' };
let obj2 = obj1;
obj2.name = 'Donald';
console.log(obj1.name); // 输出什么?
// 解析: 输出 'Donald'。因为 obj2 = obj1 是引用的复制,obj1 和 obj2 指向同一个堆内存地址。
// 通过 obj2 修改对象的属性,obj1 也会发生这个变化。

3. 类型判断

typeof

通常用于判断基本类型,但有两个特例:

  • typeof null 返回 'object' (这是一个历史遗留问题)
  • typeof 无法细分对象类型(如Array, Date)。

instanceof

用于判断一个对象是否是某个构造函数的实例 ,其原理是基于原型链的查找

js 复制代码
console.log(typeof 123); // "number"
console.log(typeof null); // "object"
console.log(typeof {}); // "object"
console.log(typeof []); // "object"

const arr = [];
console.log(arr instanceof Array); // true
console.log(arr instanceof Object); // true (因为 Array 的原型链最终指向 Object)

二、 变量声明: var, letconst

这是ES6以来前端面试的必考点,要求清晰阐述三者的核心差异。

特性 var let const
作用域 函数作用域 块级作用域 ({}) 块级作用域 ({})
变量提升 (Hoisting) 存在 (声明提升,赋值不提升) 不存在 (存在暂时性死区TDZ) 不存在 (存在暂时性死区 TDZ)
重复声明 允许 不允许 不允许
重新赋值 允许 允许 不允许

面试题代码示例

1. 作用域与变量提升

js 复制代码
// var 的变量提升
console.log(foo); // undefined
var foo = 'Hello';

// let 的暂时性死区
// console.log(bar); // Uncaught ReferenceError: Cannot access 'bar' before initialization
let bar = 'World';

2. const 的不变性

面试会考察是否理解 const 的"不变"是指针(引用)的不变,而不是其指向内容的不变。

ini 复制代码
const person = {
  name: 'Mickey',
  age: 30
};

// person = {}; // 会抛出 TypeError: Assignment to constant variable.

person.age = 31; // 这是允许的,因为我们修改的是对象内部的属性,而不是 person 变量的引用。
console.log(person.age); // 31

三、 运算符

  • 算术运算符 : +, -, *, /, % (取模), ** (ES7幂运算)。

  • 赋值运算符 : =, +=, -=, *=, /=, %=

  • 比较运算符 : ==, ===, !=, !==, >, <, >=, <=

  • 逻辑运算符 : && (逻辑与), || (逻辑或), ! (逻辑非)。

  • 三元运算符 : condition ? exprIfTrue : exprIfFalse

面试题代码示例

&&|| 具有短路特性,在实际编码中非常有用。

js 复制代码
// && (与): 如果第一个操作数为假值(false),则直接返回第一个操作数,不再计算第二个。
const result1 = 0 && console.log('This will not run');
console.log(result1); // 0

const user = { name: 'Mickey' };
const userName = user && user.name; // 安全地访问嵌套属性
console.log(userName); // 'Mickey'

// || (或): 如果第一个操作数为真值(true),则直接返回第一个操作数,不再计算第二个。
const result2 = 'Hello' || console.log('This will not run');
console.log(result2); // 'Hello'

function greet(name) {
  name = name || 'Guest'; // 为函数参数提供默认值 (ES6之前常用)
  console.log(`Welcome, ${name}`);
}
greet(); // Welcome, Guest
greet('Mickey'); // Welcome, Mickey

四、 流程控制

条件语句

  • if...else if...else: 用于处理一系列的条件判断。

  • switch: 用于基于一个表达式的值来执行多个不同的操作,通常比一长串 if...else if 更清晰。

循环语句

  • for: 最常用的循环,当循环次数已知时非常方便。

  • while: 在指定条件为真时重复执行代码块。

  • do...while: 与while类似,但至少会执行一次代码块。

  • for...of (ES6): 用于遍历可迭代对象(如 Array, String, Map, Set)的值。

代码示例

js 复制代码
// switch 语句
function getFruitColor(fruit) {
  let color;
  switch (fruit) {
    case 'apple':
      color = 'red';
      break; // break 语句至关重要,否则会发生"穿透"
    case 'banana':
      color = 'yellow';
      break;
    case 'grape':
      color = 'purple';
      break;
    default:
      color = 'unknown';
  }
  return color;
}
console.log(getFruitColor('banana')); // yellow

// for 循环
const numbers = [10, 20, 30];
for (let i = 0; i < numbers.length; i++) {
  console.log(`Element at index ${i} is ${numbers[i]}`);
}

// for...of 循环 (更简洁的遍历)
for (const number of numbers) {
  console.log(`Element value is ${number}`);
}

五、 函数

函数是JavaScript的一等公民,是组织和复用代码的基本单元。

函数声明

js 复制代码
function sum(a, b) {
  return a + b;
}

特点:存在函数提升 (Hoisting) ,即在声明之前就可以调用。

函数表达式

js 复制代码
const multiply = function(a, b) {
  return a * b;
};

特点:作为变量赋值,遵循变量的提升规则(var提升声明,let/const不提升),在赋值前无法调用。

箭头函数 (ES6)

js 复制代码
const subtract = (a, b) => a - b;

特点:语法简洁,且其 this 值由词法作用域决定,而不是由调用方式决定。

参数与返回值

函数可以接收参数,并通过 return 关键字返回一个值。如果没有 return 语句,函数默认返回 undefined

面试题代码示例 (函数提升)

js 复制代码
console.log(declaredSum(5, 5)); // 10 (正常工作,因为函数声明被提升)

function declaredSum(a, b) {
  return a + b;
}

// console.log(expressedSum(5, 5)); // TypeError: expressedSum is not a function
// (如果用var声明,变量提升了但赋值没提升,此时expressedSum是undefined)
// Uncaught ReferenceError: Cannot access 'expressedSum' before initialization
// (如果用const/let声明,存在暂时性死区)

const expressedSum = function(a, b) {
  return a + b;
};

六、 对象

创建

通常使用字面量语法 const obj = {};

属性访问

  • 点表示法 (.) : obj.key,当属性名是有效的标识符时使用。

  • 方括号表示法 ([]) : obj['key'],当属性名包含特殊字符、是变量、或需要动态计算时使用。

属性操作

  • 添加/修改 : obj.newKey = 'value';obj['newKey'] = 'value';

  • 删除 : delete obj.key;

  • for...in 循环 : 用于遍历对象自身及原型链上的可枚举属性。

代码示例

js 复制代码
const car = {
  make: 'Toyota',
  model: 'Camry',
  'year-of-manufacture': 2022, // 包含特殊字符的键
  start: function() {
    console.log('Engine started!');
  }
};

// 访问属性
console.log(car.make); // 'Toyota'
console.log(car['year-of-manufacture']); // 2022 (必须用方括号)

// 修改属性
car.model = 'Corolla';

// 添加属性
car.color = 'blue';

// 删除属性
delete car.color;

// 遍历对象
for (const key in car) {
  // 推荐使用 hasOwnProperty 确保只遍历对象自身的属性
  if (Object.prototype.hasOwnProperty.call(car, key)) {
    console.log(`${key}: ${car[key]}`);
  }
}

七、 数组

  • 创建 : const arr = [];

  • 访问 : 通过索引 arr[0]

  • length 属性: 获取或设置数组的长度。

常用方法

改变原数组

  • push() / pop(): 在末尾添加/删除元素。

  • unshift() / shift(): 在开头添加/删除元素。

  • splice(): 在任意位置添加/删除/替换元素。

  • sort(): 对数组进行排序。

不改变原数组

  • concat(): 合并数组。

  • slice(): 提取数组的一部分。

  • forEach(): 遍历数组,对每个元素执行一个函数。

  • map(): 创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

  • filter(): 创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。

  • find(): 返回数组中满足提供的测试函数的第一个元素的值。

代码示例 (map vs forEach)

js 复制代码
const ids = [1, 2, 3, 4];

// forEach: 仅用于迭代,没有返回值
ids.forEach(id => {
  console.log(`Processing ID: ${id}`);
});

// map: 用于转换数组,返回一个新数组
const urls = ids.map(id => `/users/${id}`);
console.log(urls); // ['/users/1', '/users/2', '/users/3', '/users/4']
console.log(ids);  // [1, 2, 3, 4] (原数组未改变)

八、 DOM 操作与事件模型

尽管如今的框架都封装了'完美'的DOM操作,但原生DOM API是所有上层建筑的基础。

1. 高效的DOM节点操作

当需要向DOM中添加大量元素时,直接在循环中 appendChild 会导致多次重排 (reflow)重绘 (repaint) ,影响性能。推荐使用 DocumentFragment 作为临时容器。

js 复制代码
const list = document.getElementById('my-list');
const fragment = document.createDocumentFragment(); // 创建一个文档片段

for (let i = 0; i < 1000; i++) {
  const item = document.createElement('li');
  item.textContent = `Item ${i + 1}`;
  fragment.appendChild(item); // 先将所有新节点附加到 fragment
}

list.appendChild(fragment); // 最后一次性将 fragment 添加到真实DOM,只触发一次重排。

2. 事件委托

利用事件冒泡机制,将事件监听器绑定在父元素上,统一处理子元素的事件。这在动态添加子元素的场景下尤为高效。

html 复制代码
<ul id="parent-list">
  <li>Item 1</li>
  <li>Item 2</li>
  <li>Item 3</li>
</ul>
js 复制代码
const parentList = document.getElementById('parent-list');

parentList.addEventListener('click', function(event) {
  // event.target 是实际被点击的元素
  if (event.target && event.target.nodeName === 'LI') {
    console.log(`点击了: ${event.target.textContent}`);
  }
});

九、 AJAX 与本地存储

AJAX

fetch API 是目前主流的异步请求方案,它基于 Promise,语法更简洁。

js 复制代码
async function fetchUserData() {
  try {
    const response = await fetch('https://api.example.com/user/1');

    // fetch 不会因 404/500 等 HTTP 错误状态码而 reject Promise,需要手动检查
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }

    const data = await response.json(); // 解析 JSON 响应体
    console.log(data);
  } catch (error) {
    console.error('Fetch failed:', error);
  }
}

fetchUserData();

本地存储方案对比

方案 生命周期 存储大小 与服务器通信
localStorage 永久,除非手动清除 约 5MB 否,仅在客户端
sessionStorage 浏览器标签页关闭即清除 约 5MB 否,仅在客户端
Cookie 可设置过期时间 约 4KB 每次HTTP请求都会携带

以上是JavaScript基础篇面试考察点的内容,如有错误欢迎评论区指正。

相关推荐
shaohaoyongchuang1 小时前
vue_05axios
前端·javascript·vue.js
f***14771 小时前
Node.js npm 安装过程中 EBUSY 错误的分析与解决方案
前端·npm·node.js
IT_陈寒1 小时前
React性能优化:5个90%开发者都会忽略的useEffect最佳实践
前端·人工智能·后端
梓沂1 小时前
playEdu自定义接口需要满足的格式
前端·javascript·react.js
i***22071 小时前
SpringBoot返回文件让前端下载的几种方式
前端·spring boot·后端
A达峰绮1 小时前
当企业级前端遇见AI,我们如何重新定义开发效率
前端·人工智能·状态模式
古韵1 小时前
深入alova3服务端能力:分布式BFF层到API网关的最佳实践
javascript·redis·node.js
技术钱1 小时前
react可视化标尺@scena/react-ruler使用
前端·react.js·前端框架
m0_740043731 小时前
JavaScript
开发语言·javascript·ecmascript