(Day11) 物件参考特性

传值与传参考

物件传参考是 JS 中非常重要的特性,纯值和物件在赋值时的行为模式不同:

  • 纯值在赋值时会是传值
  • 物件型别都是传参考(参考记忆体)

先来看看传值的程序码:

var name1 = 'Ryder'
var name2 = name1
name2 = 'Jack'
console.log( name1, name2 )//Ryder , Jack 

传参考范例

这个状况很好理解,name1 的资料赋值给 name2,nam2 独立修改资料,不影响 name1 ,但如果是物件的传参考状况呢?

var obj1 = { name:'Ryder' }
var obj2 = obj1
 obj2.name = 'Jack'
console.log( obj1.name ,obj2.name) //Jack , Jack 

答案会是两边都会是 Jack ,并且若再使用 console.log(obj1 === obj2) 他也会回传 true ,这是因为在 JS 中,物件赋值时是传参考的。

那什麽是传参考呢?

根据上面程序码,一行一行来讲解

  1. 首先再建立一个物件时,该物件便会创建一个记忆体,也就是范例中的:
var obj1 = { name:'Ryder' }

这样物件本就会有一个独立的记忆体,目前称做 00x1,情况大致如图:

  1. 再来 obj2 = obj1obj1 赋值给 obj2 时,其实这段就是提供物件参考的记忆体,因此称作传参考,情况如图:

    也因为 obj1obj2 的记忆体指向是相同记忆体,因此当我们使用 obj2.name 修改时,两个物件的内容都会被修改。

物件实字 {} 建立新记忆体

再来看看例外状况:
试着为 obj2 赋予新物件:

var obj1 = { name:'Ryder' }

var obj2 = obj1
obj2 = { name:'Ryder' }
connsole.log(obj1 === obj2) //false

结果之所以回传 false 是因为 obj2 有在使用物件实字 {} 建立一个新物件,此时会生成一个新的记忆体指向,用图表示就是:

特殊范例

最後来看看一个状况特别的延伸的范例:

var obj1 = { a:1 }
var obj2 = obj1
obj1.a = { a:2 }
obj1.b = obj1 = { b:1 } 
obj1 //{b: 1}
obj2 //{a: {a:2}, b: {b:1}}

这边出现的结果不论是 obj1obj2 都令人疑惑,这边一行一行来说明:

var obj1 = { a:1 }
  1. obj1 创立一个物件此时诞生一个新记忆体 00x1 ,内容是 { a:1 } ,状况如图:

  2. obj2 赋值实际获得的是 00x1 记忆体,如图:

  3. obj1 中的 a 属性从原本纯值 1 替换成新物件 { a:2 },此时也会建立新记忆体 00x2 ,如图:

  4. 接下来是重点 obj1.b = obj1 = { b:1 } 根据运算子相依性特性 obj1 = { b:1 } 会先执行,同时我们也看到 obj1 重新赋值一个新物件,因此会诞生一个新记忆体 00x3 ,并且 obj1 指向的记忆体会被更改成 00x3,如图:

  5. 接下来是将 obj1 = { b:1 } 这段回传的 { b:1 } 赋予到 obj1.b 上,但要注意的是我们输入的是 obj1.b = obj1 = { b:1 } 这段只是一行程序码,JS 实际上在编译时不会为了 obj1 = { b:1 } 马上建立一段新的记忆体,因此 obj1.b 实际指向的并非是後来变更的 00x3 而是变更前的 00x1 ,因此就会是 00x1 又塞入了 00x3 内容,如图:

    最後使用 console.log(obj1 === obj2.b) 答案也会是 true 了。

P.S. 最让人疑问的便是 obj1.b = obj1 = { b:1 } 这段。
而这段的重点是,JS 在编译这种一行执行的程序码时,是不会为了个别『运算式』去建立记忆体,因此这种一行程序码,都还是会使用原始的记忆体指向。

参考资料


<<:  Day 11 - 基本语法6(回圈2)

>>:  day11 : argo gitops服务以及ingress (上)

Day04 安装Django

经历了前两天的介绍及环境准备後,我相信大家大概都已经准备好要开始进入Django的世界了吧! 什麽?...

[Lesson28] Kotlin - Generics

泛型就是参数化类型,将类别参数化。让你在定义类别、方法、介面时先不用决定型别,等到要实体化时再决定型...

Material UI in React [ Day 16 ] Navigation Menu (下拉框)

Menu 这个套件应用的范围很广,之前讲解过的 Select 也是用这里的 MenuItem 来替换...

React和DOM的那些事-节点新增算法

点击进入React源码调试仓库。 本篇是详细解读React DOM操作的第二篇文章,文章所讲的内容发...

[深入浅出MQTT]: v3.1.1与v5 的差异

[深入浅出MQTT]: v3.1.1与v5 的差异 MQTT v3.1.1 与 v5 完全相容,且提...