你还在傻傻的认为传递分为值传递和引用传递吗?

前言

这篇文章是本人在读红宝书(第四版)4.1.3节-传递参数时引发的思考产出的最终结果,记录一下思考的过程。因为函数传参的过程其实就是变量赋值的过程,所以本文全部用变量赋值举例。若各位大佬有不同见解,欢迎探讨!

先说结论:在传递操作中只有值传递,没有引用传递。

我们大多都是把这两个概念混淆在一起,所以会觉得存在引用传递,接下来我们先区分传递和访问两种概念。

值传递是指在变量赋值的过程,并且会将原变量的值复制一份出来赋给新变量,两个变量互不相干。

ini 复制代码
const a = 1;  // 这是一次值传递操作
let b = a; // 这也是一次值传递操作
b = 2;
console.log(a); // 1  修改b的值不会影响a

访问是指读取变量值的过程,分为按值访问、按引用访问

按值访问

其实值传递的过程中会涉及到访问的操作,比如我有一个变量a值为1,现在要将a的值赋值给一个新的变量b,首先得拿到a的值才能赋值给b,在访问a的具体值的过程所使用的访问方式就是按值访问。

ini 复制代码
const a = 1;  
let b = a; // 这里需要先拿到a的值,才能赋值给b
按引用访问

按引用访问概念和按值访问差不多,我们都知道像对象、数组等等一些复杂的数据类型是存储在堆内存中的。所以我们的变量中存的是存在堆内存中数据的地址,访问该变量时会根据变量对应的内存地址去堆内存中查找对应的数据,这个访问方式称为按引用访问。

ini 复制代码
const obj = {
    a: 1
};  
const obj1 = obj; // 这里需要先拿到obj的值,也就是该对象在堆内存中的地址,才能赋值给obj1

可以看到我们在将obj的对象赋值给obj1时,实质上是复制了一份地址给obj1,因此我们可以通过更改变量的地址来使其脱离原来对象的引用。

ini 复制代码
const obj = {
  a: 1,
  b: 2,
};
let obj1 = obj;
obj1.a = "a";
console.log(obj); // { a: 'a', b: 2 }
obj1 = {}
obj1.a = "a1"
console.log(obj); // { a: 'a', b: 2 }
console.log(obj1);  // { a: 'a1' }

上述代码第一个打印结果证明obj1和obj操作的是同一个对象,因为他们所对应的是同一个堆对象地址,地址相同,所以对象相同。

接下来将obj1赋值为空对象,我们可以先理一下这一步会发生什么。首先有一个空对象,就会在堆内存中开辟一个新的空间来存储这个空对象,然后将这个新空间的地址赋值给obj1。此时obj1和obj对应的对象内存地址已经不一致了,所以接下来对obj1对象的操作不会再影响obj的对象。

所以我们通过给obj1赋值新对象的方式,使其与obj的对象脱离绑定,互不影响,这不就是值传递的概念么。

结论:只有值传递,没有引用传递!

相关推荐
_柳青杨10 小时前
深入理解 JavaScript 事件循环
前端·javascript
大家的林语冰15 小时前
ES5 凉凉,Babel 8 正式发布,默认不再编译为 ES5 和 CJS......
前端·javascript·前端工程化
weedsfly17 小时前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript
用户17335980753717 小时前
纯前端 PDF 数字签名实战:Vue 3 + pdf-lib 在浏览器里完成签名嵌入
前端·javascript
JieE2121 天前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2121 天前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
kyriewen1 天前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
Larcher1 天前
AI Loop:让AI像人一样自主完成任务的核心机制
javascript·人工智能·设计模式
默_笙1 天前
🃏 JS 只有 8 种数据类型,但我花了 2 天才搞懂 null 和 undefined 的区别
javascript
jump_jump1 天前
流式 HTML:从 htmx 片段装配到浏览器原生增量渲染
javascript·性能优化·前端工程化