JavaScript 中的引用传递 vs. 值传递
我认为理解内存以及声明变量时发生的情况非常重要。计算机内存对于人类来说可能是一个令人困惑且抽象的概念,所以我认为理解它的最佳方式是通过类比,我将在解释这一点时使用这个类比。
想象一下,你的计算机内存就像一个仓库。仓库里有一些存储箱,用于存放一箱箱的数据。声明一个变量后,你需要将一个箱子运送到仓库,然后将其存放在一个存储箱中,直到你以后需要它为止。
JavaScript 中的原始数据类型是按值传递的。如果您不确定这七种原始数据类型是什么,没关系。我建议您停下来读读这篇文章,了解一下。您可能在学习的过程中都见过它们,但了解它们之间的区别会有所帮助。MDN :JavaScript - 数据结构。
假设你将一个变量设置为等于另一个变量。例如:
let box1 = 'sugar'
let box2 = box1
让我们来分解一下……在我们众所周知的仓库里,一名工人走到箱子box1
所在的位置,检查箱子,然后使用 JavaScript 魔法创建一个完全相同的副本。然后,工人将副本搬走,并将其存放在新的箱子中box2
。
您会看到,该值box1
已被复制,并且box2
两者都有'sugar
“。”
那么,如果我们改变其中一个值会怎样?
box2 = 'brown sugar'
console.log(box1) // returns 'sugar'
console.log(box2) // returns 'brown sugar'
它们不再相同了,不过没关系。只是传递了box2
创建时的原始值,它们彼此之间没有任何关联,因此不会相互影响。
JavaScript 中的对象使用引用传递。我们使用的 JavaScript 中的大多数结构都是对象,所以我认为理解它的工作原理非常重要。对象{}
由键值对、数组和函数等组成。你可能听过“JavaScript 中的一切都是对象”这句话。这话确实有道理!
const box3 = {
contents: "salt"
}
const box4 = box3
在这个例子中,我们的小小工人识别出这box3
是一个对象。于是他草草地记下了它在仓库中的位置。然后,它快速跑到一个打开的容器旁box4
,把纸贴在架子上,标明了容器的位置box3
和里面的内容。
这就是引用传递。有时,我们创建或拉取到应用中的对象可能非常庞大,包含数百甚至数千个键值对。每次都进行克隆会非常浪费资源,而且会降低计算机的性能。
所以,它只是引用而已。有时这可能会产生无法预料的后果。
box4.contents = "pepper"
console.log(box3.contents) //returns "pepper"
console.log(box4.contents) //returns "pepper"
等等!我们不是故意的。为什么会这样?
因为box4
不包含自身的值,它包含对 的引用box3
。通过更新 的contains
属性box4
,我们实际上是在告诉它更新box3.contains
。
这正是差异给我们带来麻烦的地方。那么,问题来了,我们如何克隆box3
,而不是传递引用呢?
好吧,ES6 为我们提供了一种非常干净且好用的方法来实现这一点,即扩展运算符。
box4 = { ...box3 }
如果愿意,您还可以使用可靠的旧克隆方法。
box4 = Object.assign({}, box3)
请注意,这只是关于这些概念工作原理的一个非常基础的入门介绍。我希望我的例子和仓库类比能帮助你们更好地理解它们之间的区别,而不仅仅是阅读定义。不妨尝试一下,做个实验。此外,请深入挖掘,因为它对于在应用程序中处理数据非常重要。
我保证,在某个时刻,你会与它相遇或碰到它。
编辑:我从一个非常有信息量的评论中发现,这比第一次出现的要微妙一些,有关更多信息,请查看此帖子:https://dev.to/xpbytes/javascript-ruby-and-c-are-not-call-by-reference-23f7
鏂囩珷鏉ユ簮锛�https://dev.to/bbarbour/passed-by-reference-vs-value-in-javascript-2fna