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

前言

这篇文章是本人在读红宝书(第四版)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的对象脱离绑定,互不影响,这不就是值传递的概念么。

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

相关推荐
Black蜡笔小新5 分钟前
网页直播/点播播放器EasyPlayer.js播放器OffscreenCanvas这个特性是否需要特殊的环境和硬件支持
前端·javascript·html
Dread_lxy1 小时前
vue 依赖注入(Provide、Inject )和混入(mixins)
前端·javascript·vue.js
奔跑草-2 小时前
【前端】深入浅出 - TypeScript 的详细讲解
前端·javascript·react.js·typescript
羡与2 小时前
echarts-gl 3D柱状图配置
前端·javascript·echarts
前端郭德纲3 小时前
浏览器是加载ES6模块的?
javascript·算法
JerryXZR3 小时前
JavaScript核心编程 - 原型链 作用域 与 执行上下文
开发语言·javascript·原型模式
帅帅哥的兜兜3 小时前
CSS:导航栏三角箭头
javascript·css3
渗透测试老鸟-九青3 小时前
通过投毒Bingbot索引挖掘必应中的存储型XSS
服务器·前端·javascript·安全·web安全·缓存·xss
龙猫蓝图3 小时前
vue el-date-picker 日期选择器禁用失效问题
前端·javascript·vue.js
夜色呦3 小时前
掌握ECMAScript模块化:构建高效JavaScript应用
前端·javascript·ecmascript