a={v:1}, b=a, b.v=3, b==a?

这个问题怎么取名我有点楞,是和内存有关吧(⊙o⊙)…

var a = {v: 1}
var b = a
b.v = 2

a.v == b.v  // true

我希望在改变b.v的时候a不变,应该怎么写?

阅读 3.6k
7 个回答
var a = {v: 1}
    var b = JSON.parse(JSON.stringify(a))
    b.v = 2
    
    a.v == b.v  // false
    
    
    

或者

var a = {v: 1}
var b = Object.assign({}, a);
b.v = 2

a.v == b.v  // false

正如你说,就是和内存有关。
var a = {v: 1}
开辟一块内存,存放{v:1},变量a指向这个内存块。可理解为a为这块内存了引用。
var b = a;
a的内容复制到变量b,也就是存放{v:1}的内存引用,此时b也指向了那块内存。
b.v = 2;
修改了b指向的那块内存的内容。所以a指向的内存内容也就修改了。所以a.v == b.v;

想要他们不相等,只要定义b变量的时候,重新开辟一块内存就好了。
楼上有回答已经给出了方法。
实战项目中,我们常常采用lodashcloneDeep方法

var a = {v : 1}
var b = Object.assign({},a)
b.v = 2
a.v == b.v //false

像a这种情况,可以使用深度拷贝将值赋给b

var b = JSON.parse(JSON.stringify(a));

当然这里a只有一层属性,也可以使用

var b = Object.assign({}, a);

这个方法有很多,Object.assign() ...运算符。还有上面说的stringify 和parse。
其实是一个拷贝的问题:Object.assign 和 ... 属于浅拷贝。JSON.parse(JSON.stringify())不能拷贝原型对象。这之中的问题。楼主可以自己搜索下。
另外 内存储存类型:堆和栈。也可以去baidu/google下。

问题解析

var a = {v: 1}
这一步假设分布了内存0x001给a,此时a => 0x001, 0x001存放了{v: 1}(简单理解成这样)
var b = a
这一步相当于b => 0x001
也就是说b = {v: 1},因为b地址也指向0x001
b.v = 2
这一步的时候,0x001中的v = 2
b => 0x001 => .v => 2
a => 0x001 => .v => 2
所以 a.v == b.v // true
这些都是因为至两个变量指向了同一个地址

解决思路

使两个变量的指向为不同的地址

  1. 可以转换成字符串再转成对象()

var b = JSON.parse(JSON.stringify(a))

  1. es6中 合并两个对象,源是a,目标是空对象。也能达到不同地址的目的

var b = Object.assign({}, a);

对于一层的对象可以这样

b = {...a}

题目的语法过程。

在生成一个{v:1}存在堆地址0x0001
a指向地址0x0001
b指向a的地址0x0001
修改此地址的v的值
a/b指向相同,所以。。。
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题