JavaScript 函数参数传递机制:一道经典面试题解析

前言

在 JavaScript 面试中,参数传递机制是一个常见考点。很多人对"对象作为参数传递"这一概念存在误解。本文将通过一道经典面试题,带你彻底理解 JavaScript 的参数传递机制。

题目代码

javascript 复制代码
function test(person) {
  person.age = 26
  person = {
    name: 'hzj',
    age: 18
  }
  return person
}
const p1 = {
  name: 'fyq',
  age: 19
}
const p2 = test(p1)
console.log(p1) // 输出什么?
console.log(p2) // 输出什么?

答案解析

输出结果

javascript 复制代码
console.log(p1) // { name: 'fyq', age: 26 }
console.log(p2) // { name: 'hzj', age: 18 }

详细解析

1. JavaScript 的参数传递机制

首先要明确:JavaScript 中所有函数参数都是按值传递的。这是一个关键点,很多人会误解为"对象按引用传递"。

  • 基本类型:传递的是值的副本
  • 引用类型:传递的是引用的副本(可以理解为指针的副本)

2. 代码执行过程分析

第一步:函数调用前

javascript 复制代码
const p1 = {
  name: 'fyq',
  age: 19
}

此时内存中存在一个对象,p1 保存着指向这个对象的引用。

第二步:调用 test(p1)

javascript 复制代码
function test(person) {
  // 此时 person 和 p1 指向同一个对象
  person.age = 26  // 修改了原始对象的属性
  // ...
}

当调用 test(p1) 时,实际上是将 p1 保存的引用复制了一份传递给 person 参数。此时 personp1 指向内存中的同一个对象。

执行 person.age = 26 时,通过这个引用修改了原始对象的 age 属性。因此,p1 指向的对象已经被改变。

第三步:重新赋值 person

javascript 复制代码
function test(person) {
  // ...
  person = {
    name: 'hzj',
    age: 18
  } // person 现在指向一个新对象
  // ...
}

这里的关键点:person = {...} 并不是修改原始对象,而是将局部变量 person 重新赋值为一个新对象的引用。这切断了 person 与原始对象的关联,但不会影响 p1 仍然指向原始对象。

第四步:函数返回并赋值

javascript 复制代码
return person // 返回新对象的引用
const p2 = test(p1) // p2 指向函数返回的新对象

函数返回了新对象的引用,p2 接收了这个引用,指向新创建的对象 {name: 'hzj', age: 18}

核心概念总结

值传递 vs 引用传递

  • 值传递:传递的是变量的副本,修改参数不会影响原始变量
  • 引用传递:传递的是变量的实际地址,修改参数会影响原始变量
  • JavaScript 的情况:对于对象类型,传递的是引用的副本(可以称为"共享传递")

关键区别

操作类型 对原始对象的影响 示例
修改对象属性 ✅ 会影响原始对象 person.age = 26
重新赋值参数 ❌ 不会影响原始对象 person = {...}

实际应用场景

理解这一机制对于避免以下常见错误至关重要:

  1. 意外修改原始数据:在函数中修改传入对象的属性时,可能会意外改变原始数据
  2. 函数式编程:需要保持数据不可变性时,应该先创建副本再修改
  3. 状态管理:在 React 等框架中,直接修改状态对象会导致无法检测到状态变化

思考题

如果你希望函数内部的操作不影响原始对象,应该怎么做?

javascript 复制代码
// 解决方案:创建对象的副本
function test(person) {
  const newPerson = {...person} // 浅拷贝
  newPerson.age = 26
  // ... 其他操作
  return newPerson
}

结语

JavaScript 的参数传递机制虽然简单,但理解其细微差别对于编写可靠的代码至关重要。记住:对象作为参数传递时,传递的是引用的副本,修改属性会影响原始对象,但重新赋值参数变量不会影响原始对象

相关推荐
brzhang17 小时前
为什么 OpenAI 不让 LLM 生成 UI?深度解析 OpenAI Apps SDK 背后的新一代交互范式
前端·后端·架构
brzhang17 小时前
OpenAI Apps SDK ,一个好的 App,不是让用户知道它该怎么用,而是让用户自然地知道自己在做什么。
前端·后端·架构
爱看书的小沐18 小时前
【小沐学WebGIS】基于Three.JS绘制飞行轨迹Flight Tracker(Three.JS/ vue / react / WebGL)
javascript·vue·webgl·three.js·航班·航迹·飞行轨迹
井柏然18 小时前
前端工程化—实战npm包深入理解 external 及实例唯一性
前端·javascript·前端工程化
IT_陈寒19 小时前
Redis 高性能缓存设计:7个核心优化策略让你的QPS提升300%
前端·人工智能·后端
aklry19 小时前
elpis之动态组件机制
javascript·vue.js·架构
井柏然19 小时前
从 npm 包实战深入理解 external 及实例唯一性
前端·javascript·前端工程化
羊锦磊19 小时前
[ vue 前端框架 ] 基本用法和vue.cli脚手架搭建
前端·vue.js·前端框架
brzhang20 小时前
高通把Arduino买了,你的“小破板”要变“AI核弹”了?
前端·后端·架构
她说..20 小时前
通过git拉取前端项目
java·前端·git·vscode·拉取代码