七爪源码:差异通过参考与通过价值

今天我们将讨论 Javascript 中最基本的概念之一“按值传递”和“按引用传递”。 这个概念非常重要,甚至这个问题也经常出现在求职面试中。 这是为什么? 了解它是如何工作的,它将帮助我们成为更好的程序员,能够理解应用程序中的数据流。

在我们深入解释之前。 我们必须知道,在 Javascript 中数据类型分为两类:原始的和非原始的。

以下是 Javascript 中的原始数据类型列表:

  • string - 一个字符数组
  • number - 整数、浮点数等...
  • bigint - 如果您需要大于 Number 支持的范围的整数值
  • boolean - 真或假
  • null - 空值
  • symbol - 唯一值或经常用作不等于任何其他值的唯一标识符
  • undefined - 声明的变量,但仍未分配值。

同时,所有对象、数组和函数都属于非原始数据类型。

好的,我们得到了这个。 让我们进入解释!


通过引用传递

我们通过下面的代码来了解一下引用传递的是什么

let john = {  name: 'John Doe',  gender: 'male',  score: 95};let JohnDupe = john;console.log(JohnDupe); // {name: 'John Doe', gender: 'male', score: 95}console.log(john); // {name: 'John Doe', gender: 'male', score: 95}

好的,我们创建了一个新变量 JohnDupe,并为 John 赋值。 如果我们修改 JohnDupe 的分数,接下来会发生什么?

johnDupe.score = 50;console.log(JohnDupe); // {name: 'John Doe', gender: 'male', score: 50}console.log(john); // {name: 'John Doe', gender: 'male', score: 50}

请注意,他们对 John 的价值得分也发生了变化! 究竟发生了什么? 当我们创建 John(一个新对象)时,我们将值存储在某个地址的内存中。 而当我们将 John 的值分配给 johnDupe 时,实际上不是创建 John 的副本,JohnDupe 的值是引用内存中 John 的值(地址)。

要解决上述问题,我们需要实际创建 John 的副本并将其分配给一个新变量,然后我们可以在不影响原始 John 的情况下更改分数。

let john = {  name: 'John Doe',  gender: 'male',  score: 95};let anotherJohn = {...john}anotherJohn.score = 50;console.log(john); // {name: 'John Doe', gender: 'male', score: 95}console.log(anotherJohn); // {name: 'John Doe', gender: 'male', score: 50}

在上面的代码中,我们使用扩展运算符复制了 john,然后将其分配给 anotherJohn。 通过创建一个新对象,anotherJohn 实际上将复制的对象存储在与 john 不同的地址的内存中。 anotherJohn 不再像以前那样引用 john,它们是完全不同的实体。 为了证明这一点,请看下面的代码

let person = {  name: 'Nicola Tesla',  gender: 'male',};let personDupe = person;let anotherPerson = {  name: 'Nicola Tesla',  gender: 'male',};console.log(person === personDupe); // trueconsole.log(person === anotherPerson); // false

在上面的示例中,我们尝试比较相等的 person === personDupe,这将打印为 true,因为 personDupe 指向的是 person 的地址。 但是,当我们尝试比较一个相等的人 === anotherPerson 时,这将打印为 false,因为即使它们具有相同的属性和值,它们也不是同一个对象。

这种行为也与 Array 相同。

let fruits = ['apple ', 'strawberry ', 'banana '];let fruitsDupe = fruits;let anotherFruits = ['apple ', 'strawberry ', 'banana '];console.log(fruits === fruitsDupe); // trueconsole.log(fruits === anotherFruits); // false

我有一个类比,通过假设它是一个谷歌表/谷歌文档,让我们更容易理解“通过引用”。

假设一群学生被老师分配给他们对全球变暖的看法。老师希望作业的格式在一个文件中。

约翰作为班长主动创建了一个谷歌文档,以便学生可以轻松协作。约翰然后与他的同学分享链接。 Mary 是第一个更改文档并添加一堆关于全球变暖的想法的学生。那天晚上晚些时候,苏西打开了谷歌文档并添加了她自己的意见,然后是安迪等。最后,在所有学生都添加完自己的意见后,John 将 google docs 分享给了老师。一切都很好,班级的作业得了“A”

从上面的案例来看,google docs无论被学生修改多少次,最终还是只修改了一个文件(主文件)。

到目前为止,一切都很好!我们知道传递引用到底是什么。


按值传递

如果您已经了解了按引用传递,那么您就已经了解了按值传递是什么。诸如数字或字符串之类的原始值实际上会创建一个副本。

const num = 10function passByValue(val) {  return val += 1}console.log('[passByValue]:', passByValue(num)) // [passByValue]: 11console.log('[num]:', num) // [num:] 10

在上面的代码中,我们创建了一个值为 10 的变量 num。此外,我们创建了一个函数 passByValue,它接受一个值作为参数并将其加 1。如果我们试图运行上面的代码,passByValue 将返回 11 ,但是num变量仍然是10。num的原始值根本没有改变。


结论!!

希望这篇短文能帮助你理解传递引用和传递值的概念。 按值传递和按引用传递的主要区别在于,按值传递将在内存中创建一个新空间并复制一个值。 但是通过引用传递而不是复制,存储在内存中的值被引用。

关注七爪网,获取更多APP/小程序/网站源码资源!

发表评论
留言与评论(共有 0 条评论) “”
   
验证码:

相关文章

推荐文章