连续赋值php,一次连续赋值体验

这篇文章上次修改于 336 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

最近在github上看到了一道很有意思的关于JS的连续赋值的题,感觉细节很多,所以拿出来分享一下var a = { n:1 };

var b = a;

a.x = a = { n:2 };

console.log(a.x); // undefined

console.log(b); // { n:1, x:{n:2} }

首先,在探索这个问题的时候,我认为需要有以下几个知识储备:JavaScript 数据类型与指针指向性

赋值运算符与运算顺序

JavaScript数据类型及指针指向

JavaScript的数据类型分为两类,一类是存在值存于栈内存的基本数据类型,一类是值存于堆内存中的引用数据类型

与其他语言不同的是,JavaScript不允许直接对内存进行操作(这里指的是对象赋值的时候,其实对对象属性进行操作的时候还是会对内存进行操作),考的是引用对对象进行赋值操作。

也就是说,我们对变量赋予引用类型的值的时候(比如对象),其实赋予的是这个对象的引用(可以理解为这个对象在内存中的地址)

赋值运算符与运算顺序

JavaScript中的赋值运算符 = 的优先级是除了 , 以外最低的,并且是从右向左结合的

譬如:var a = b = 1;

其实可以看作:var a = (b = 1);

而 JavaScript 中的运算顺序是从左向右的。

什么意思?我们一起带着这点知识储备来看看题吧

过程分析

第一行:var a = { n:1 };

这一步很好理解,声明了一个变量 a ,并且给这个变量赋予了一个对象,而这个变量在栈内存中存的值是这个对象的引用,这个引用指向的是堆内存中的某个值,这个值为 { n:1},为了方便后续的理解,我将这个值所存在的堆内存空间叫做 N

2a0065e07cd11228a4606da2d55b7c82.png

第二行:var b = a;

这一行也好理解, 创建一个变量b,为其赋值对象a。在栈内存中,a与b是不同的,是两个变量,但是他们的指针是相同的,指向同一个堆,也就是我们的 N , 因为他们栈内存中存的值是一样的,都是同一个地址

acc43f8eb151c7f5308c5e63aa7ac72d.png

第三行:a.x = a = { n:2 };

这一行便是整个题目的核心。这一行我们可以看作:a.x = (a = { n:2 });

还记得刚刚说的 JavaScript 中的运算顺序是从左向右的 吗?

这里我们的 a.x 先进行了运算,它在我们 a 所指的堆内存中创建了一个新的属性 x , 并且赋予了初始值 undefined, 也就是 N 中多了一个 x 属性

创建完成后,左侧的引用已经指向了 N中的x,并且会先挂起,等待右侧的 a = { n:2 } 的运算结果,再进行赋值。

我们来看看右侧的赋值。需要注意的是,右侧的赋值完成后,我们的 a 便不再指向 N,而是指向 {n:2} 这个对象。

由于我们的变量 b 还存放着 N 的地址 , 所以导致我们的 N 并没有因为 a 更改引用而被销毁。

88af091f817f01ca8ce1272f1ae947d0.png

好了,现在右侧的赋值完成了,我们也将最终的结果赋值给我们 N中的x属性,也就是赋予 {n:2}这个对象的引用给我们的 x

其实上面的这行代码我们可以看作:b.x = undefined;

a = { n:2 };

b.x = a;

接下来我们再来打印下a 和 b,结果其实就相当于:a = {

n:2

}

b = {

n:1,

x: {

n:2

}

}

因为直接引用一个对象不存在的成员时,会自动地进行创建并且赋予初始值undefined,所以此时打印 a.x 便会得到 undefined

我觉得这道题还是挺坑的,也有很大的变化空间。譬如 var b = a; 这个点,因为这个所以才不会使得 a 改变引用的时候将原有的堆内存空间销毁,大家可以试试再在这上面做文章进行一个举一反三的变化。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值