js 如何实现对象值复制?

2021-12-08 10:32:10 +08:00
 wunonglin

go 的实现

package main

import "fmt"

type M struct {
	Num int64
}

func T1() {
	fmt.Printf("----T1----\n")
	a := M{1}
	b := a
	fmt.Printf("%+v\n", a)
	fmt.Printf("%+v\n", b)
	a.Num = 2
	fmt.Printf("%+v\n", a)
	fmt.Printf("%+v\n", b)
}

func T2() {
	fmt.Printf("----T2----\n")
	a := &M{1}
	b := a
	fmt.Printf("%+v\n", a)
	fmt.Printf("%+v\n", b)
	a.Num = 2
	fmt.Printf("%+v\n", a)
	fmt.Printf("%+v\n", b)
}

func main() {
	T1()
	T2()
}

输出结果

----T1----
{Num:1}
{Num:1}
{Num:2}
{Num:1}
----T2----
&{Num:1}
&{Num:1}
&{Num:2}
&{Num:2}

js 的实现

function T2(){
    let a = {num: 1}
    let b = a
    console.log(a)
    console.log(b)
    a.num = 2
    console.log(a)
    console.log(b)
}

输出结果

{num: 1}
{num: 1}
{num: 2}
{num: 2}

如何使用 js 实现 golang 的 T1 方法?除了深拷贝。

就类似于“从源 Object 创建一个新的 Object ,内存地址完全是新的,新 Object 也和源完全一样,不会丢失各种属性”,js 自带的好像没看到类似的方法

2732 次点击
所在节点    程序员
39 条回复
en20
2021-12-08 10:36:52 +08:00
最简单的 JSON.parse(JSON.stringify())
NathanDo
2021-12-08 10:38:19 +08:00
const b = JSON.parse(JSON.stringify(a));
anjianshi
2021-12-08 10:38:43 +08:00
如果是普通对象,没有 method 之类的东西,且不考虑性能,可以 JSON 化。

```javascript
const objectA = {
a: {
b: { c: 1 },
d: 2,
},
e: 3
}

const objectB = JSON.parse(JSON.stringify(objectA))

objectA.a.d = 100
objectB.a.d = 200

console.log(objectA.a.d) // 100
console.log(objectB.a.d) // 200
```
anjianshi
2021-12-08 10:39:00 +08:00
哈哈哈哈 一楼抢答了
viewweiwu
2021-12-08 10:39:00 +08:00
1. let b = Object.assign({}. a)
2. let b = {...a}
3. JSON.parse(JSON.stringify(a))

这三种方法都可以
viewweiwu
2021-12-08 10:39:50 +08:00
1. let b = Object.assign({}, a)
2. let b = {...a}
3. JSON.parse(JSON.stringify(a))

这三种方法都可以
tsanie
2021-12-08 10:44:30 +08:00
Object.assign 和{...a}是浅拷贝。
JSON.parse(JSON.stringify(a))是深拷贝但没法处理函数。
自己写递归或者用 lodash 的 cloneDeep 吧。
wunonglin
2021-12-08 10:48:14 +08:00
@NathanDo #2
@anjianshi #3
@anjianshi #4
@viewweiwu #5

```js
class M {
get K(){
return this.Num + 1
}

constructor(value) {
this.Num = value
}
}

function T1(){
console.log('----T1----')
const a = new M(1)
const b = a
console.log(a)
console.log(b)
a.Num = 2
console.log(a, a.K, a instanceof M)
console.log(b, a.K, b instanceof M)
}

function T2_JSON(){
console.log('----T2_JSON----')
const a = new M(1)
const b = JSON.parse(JSON.stringify(a))
console.log(a)
console.log(b)
a.Num = 2
console.log(a, a.K, a instanceof M)
console.log(b, a.K, b instanceof M)
}

function T2_Assign(){
console.log('----T2_Assign----')
const a = new M(1)
const b = Object.assign({}, a)
console.log(a)
console.log(b)
a.Num = 2
console.log(a, a.K, a instanceof M)
console.log(b, a.K, b instanceof M)
}

function T2_Spread(){
console.log('----T2_Spread----')
const a = new M(1)
const b = {...a}
console.log(a)
console.log(b)
a.Num = 2
console.log(a, a.K, a instanceof M)
console.log(b, a.K, b instanceof M)
}

T1()
T2_JSON()
T2_Assign()
T2_Spread()
```

使用 json ,assign ,spread 后原型丢了。不符合需求
wunonglin
2021-12-08 10:48:46 +08:00
```
----T1----
M { Num: 1 }
M { Num: 1 }
M { Num: 2 } 3 true
M { Num: 2 } 3 true
----T2_JSON----
M { Num: 1 }
{ Num: 1 }
M { Num: 2 } 3 true
{ Num: 1 } 3 false
----T2_Assign----
M { Num: 1 }
{ Num: 1 }
M { Num: 2 } 3 true
{ Num: 1 } 3 false
----T2_Spread----
M { Num: 1 }
{ Num: 1 }
M { Num: 2 } 3 true
{ Num: 1 } 3 false
```
yaphets666
2021-12-08 10:50:52 +08:00
除了深拷贝?为啥要把他除了啊.jsonstringify 我劝你别用 会丢失数据结构
wunonglin
2021-12-08 10:52:37 +08:00
@yaphets666 #10

类似于 b = Object.from(a),这样能够实现 golang 的效果,这个 from 是不存在的,举例而已
gadfly3173
2021-12-08 10:55:08 +08:00
yaphets666
2021-12-08 10:55:29 +08:00
@wunonglin js 没有原生的这种功能,如果想完美的实现一个复杂数据结构对象的值复制,必须使用深拷贝,自己实现一个或者使用第三方库.上面说的 object.assign 和 JSON.stringify 都有各自的局限性,你可以自行百度.
gadfly3173
2021-12-08 10:58:02 +08:00
“从源 Object 创建一个新的 Object ,内存地址完全是新的,新 Object 也和源完全一样,不会丢失各种属性”
这个需求不就是深拷贝么,,,除了深拷贝还能咋实现呢
anjianshi
2021-12-08 10:58:32 +08:00
要保留原型,就只能用笨方法了。
wunonglin
2021-12-08 11:03:00 +08:00
@gadfly3173 #14 原生方法,非第三方
anjianshi
2021-12-08 11:05:08 +08:00
涉及到 class 的东西,是没法做到“复制”的。go 里我记得是没有 class 之类的概念,你才能用系统提供的能力去复制。
只有“普通对象”,可以快捷复制。
wunonglin
2021-12-08 11:05:22 +08:00
@yaphets666 #13
@gadfly3173 #12

lodash 的 cloneDeep 可以实现。但是我想知道有没有原生的方法
anjianshi
2021-12-08 11:05:47 +08:00
所以,要么不要带 class ,要么自己手动深拷贝。
WhiteHu
2021-12-08 11:08:07 +08:00
structuredClone()

有自带的方法哈 不过是试验性 api

https://developer.mozilla.org/en-US/docs/Web/API/structuredClone

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/820807

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX