symfony修改user对象_JS面向对象系列教程 — 内存中的对象

bc2f683109ed4a5237ddbadd34a0a7e5.png
当我们创建了一个对象,然后赋值给一个变量后,内存中究竟发生了什么?如果把一个保存了对象的变量赋值给另外一个变量,它们是同一个对象吗?
以上问题,就是本章要理清楚的内容。本章将深入到底层,去查看对象创建后内存中究竟发生了什么事。
了解本章的内容,可以让你对对象有一个更加清晰的认识,也会规避一些常犯的低级错误。

对象的赋值

const user = {
    loginid: "bangbangji",
    loginpwd: "123456",
    name: "棒棒鸡"};

上面的代码创建了一个对象,然后赋值给了一个变量user,完整的描述如下:

  1. 内存中开辟了一块空间,来存放对象的三个属性
  2. 将该内存区域的地址保存到变量user中

结果就是,变量user中保存的内存地址,指向了对象所在的内存空间,如下图所示:

现在,我在上面的代码基础上加一句:

let user2 = user;

这句代码是什么意思呢?我们知道,把一个变量的值赋值给另一个变量,是指将变量中保存的东西赋值给另一个变量。而这里的变量user保存的是什么呢?对了,是某个对象的内存地址,将其赋值给变量user2,因此user2中也保存了相同的内存地址。如下图:

那么,现在,我试着改变user2中的属性:

user2.loginpwd = "666";console.log(user.loginpwd, user2.loginpwd); //将输出什么呢?console.log(user === user2); //将输出什么呢?
注:对象之间的严格相等比较(===)和相等比较(==)一样,都是比较两个对象的地址是否相同。

试着结合前面的原理图,看你是否能说出上面代码的运行结果。

由于useruser2中保存的相同的内存地址,指向的是同一个对象,因此,通过user2修改了对象的登录密码,user指向的对象也同时得到了修改,因为它们指向的是同一个东西:

因此,上面的代码输出:

666 666
true

那现在我继续增加代码,现在我要对user2进行重新赋值,看看又会怎样呢?

user2 = {
    loginid: "bbj",
    loginpwd: "666",
    name: "棒棒鸡"};console.log(user.loginid, user2.loginid); //将输出什么呢?console.log(user === user2); //将输出什么呢?

这种情况下,useruser2还指向的是同一个对象吗?不再是了!因为我又新创建了一个对象(回忆一下上一节的知识,使用{}new都表示创建对象),并把这个新的对象地址保存到user2中,如下图:

因此,上面的代码输出:

bangbangji bbj
false

面对多层次的对象结构,道理是一样的:

const user1 = {
    loginid: "bangbangji",
    loginpwd: "123456",
    name: "棒棒鸡",
    address: {
        province: "四川省",
        city: "成都市"
    }
};const user2 = {
    loginid: "xiaobaitu",
    loginpwd: "654321",
    name: "小白兔"};//将user1中属性address保存的地址赋值给user2的属性addressuser2.address = user1.address;
user2.address.city = "广元市";console.log(user1.address.city, user2.address.city); //输出:?

当代码user2.address = user1.address;运行后,会得到如下的内存结构图:

虽然user1user2保存着两个不同的地址,分别指向两个不同的对象,但它们的属性address却保存着相同的地址,指向的是同一个对象。

因此,上面的代码运行完成后输出的结果为:广元市 广元市

如果你理解了上面的知识,请判断下面代码的执行结果:

const user1 = {
    loginid: "bangbangji",
    loginpwd: "123456",
    name: "棒棒鸡"};let user2 = {
    loginid: "bangbangji",
    loginpwd: "123456",
    name: "棒棒鸡"};
user2.loginid = "bbj";console.log(user1 === user2); //输出:?console.log(user1.loginid, user2.loginid); //输出:?user2 = user1;
user2.loginpwd = "654321";console.log(user1 === user2); //输出:?console.log(user1.loginpwd, user2.loginpwd); //输出:?console.log({} === {}); //输出:?

答案如下:

false
bangbangji bbj
true
654321 654321
false
值得玩味的是最后一句代码,直接创建两个对象进行比较(不要忘了上一章的知识, {}new都是在创建对象),由于是两个新创建的对象,它们的地址自然不同,因此并不相等。

对象的销毁

每个对象都会在内存中占用一块空间,如果一个对象不再使用,就应该销毁它,将这块内存空间腾出来,以作他用。

我们将销毁对象、腾出空间的过程叫做垃圾回收

好在很多高级语言不再需要我们手动的进行垃圾回收,它们本身自带了一个垃圾回收器,会自动处理,javascript也是如此。

垃圾回收器会不断的遍历内存中存在的对象,找出那些不再使用的对象,将其销毁,回收它所占用的内存空间

可是,垃圾回收器怎么知道哪些对象不再使用了呢?

它是通过判断引用计数来完成的,若一个对象的引用计数为0,则该对象永远无法再访问到,它将在垃圾回收器下一次扫描内存时被回收掉。

所谓对象的引用计数,是指持有该对象的内存地址,被记录的数量,下面是一个例子。

let user = {
    loginid: "bangbangji",
    loginpwd: "123456",
    name: "棒棒鸡"};let user2 = user;

上面的代码运行后,内存中存在一个对象,该对象的地址被记录了两次(存在于两个变量中),那么该对象的引用计数为2,不会被回收。

若在上面代码的基础上追加下面的代码:

user = null;
user2 = null;

现在,刚刚创建的对象的引用计数就变成了0,因为现在没有任何空间记录了它的内存地址。

[

原文转自朗沃易课堂,原文链接:JS面向对象系列教程 - 内存中的对象

更多精彩内容可以搜索“朗沃”公众号,了解更多!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值