开发用到了 AntV G6 ,然后发现有一个对象的字段怎么都获取不到,但是直接打印对象又能看到这个字段。具体来说是这样:
我想通过一个内置的方法来设置边的属性,需要拿到 edge 对象的 targetNode 字段。直接用 console.log 打印 edge 方法是能看到确实有一个 targetNode 字段的,但是实际运行的时候 edge.targetNode 的值一直是 undefined 。接下来我就发现直接打印 edge 输出的结果和打印 JSON.stringify(edge)看到的结果是不一样的,前者会多出好几个字段。
这是个什么原理?为什么会有这种状况出现?这种条件下我怎么才能获取到我想要的 targetNode 字段呢?
1
R1hu6Hs2sSN8pkVX 2023-12-08 14:43:46 +08:00
有没有可能你操作完之后这个 targetNode 被改成 undefined 得了,stringfy 的时候只是字符串不会和原来对象有引用关系
|
2
WangLiCha OP @whatFoxSay 没有操作过啊,我对 edge 对象的所有操作就是这一行打印了。另外 log 打印出来的对象会被引用影响的话不会干扰开发调试吗?
|
3
flyqie 2023-12-08 14:49:21 +08:00 via Android
JSON.stringify 跟 console.log 的结果一定会有差异,JSON.stringify 只会处理标准值,但 js 里面的黑魔法太多,所以你最好还是看下那些字段是怎么加上的。。
|
4
codehz 2023-12-08 14:49:55 +08:00
祖传问题了,devtools 点开直接打印的对象的时候会当场求值,如果那时候引用被改了就凉了,我记得 chrome 甚至会给一个警告
|
6
cxe2v 2023-12-08 14:51:08 +08:00 1
直接 console.log 输出是这个对象的引用,内部的字段在 console 的时候不一定有最后你展开时候查看到的值
JSON.stringify 是把对象字符串化,得到的结果就固定在 stringify 这个时刻 你这个情况的原因是因为 targetNode 这个字段是在你 console 之后才被添加到 edge 对象里的 解决方法,尝试通过 nextTick 或者 setTimeout 延迟获取 targetNode |
7
liuhuihao 2023-12-08 14:53:54 +08:00
原因是 devtools console.log 的时候有些时候是你点击展开的时候才去获取这个值而不是打印的时候的值。
至于 console.log 和 JSON.stringify 不一样的原因那就他太多了,toJSON 方法、undefined 、非可枚举一类的都不会出现在 JSON.stringify 里,但你发的这个问题应该不是这个导致的。单纯是你打印的时候本身就是 undefined ,然后在你展开属性的时候获取的是改后的值 |
8
liuhuihao 2023-12-08 15:02:07 +08:00 1
@liuhuihao
const a = {a:{}} console.log(a,JSON.stringify(a)) a.targetNode=123 简单的代码可以试一下 console.log 打印的是对象的引用,你后给这个对象加上属性也会出现在 log 里 |
9
liuhuihao 2023-12-08 15:07:11 +08:00
@WangLiCha 你 打印 的时候这个对象里其实还没有 targetNode 字段,这也就是为啥 JSON.stringify 里没有,这个 targetNode 字段是在你 console.log 代码执行之后、点击 devtools 对象的展开之前 才被添加到对象上的。
|
10
guorenjie 2023-12-08 15:19:56 +08:00
|
11
wangtian2020 2023-12-08 15:27:25 +08:00
打印的是对象引用,要么加上 debugger 暂停下面的代码,要么完全拷贝一份对象并且保证切断对象间的数据引用
|
12
NerbraskaGuy 2023-12-08 17:24:37 +08:00
用 proxy 做数据监听吧,json stringfy 会因为各种限制导致数据丢失
|
13
shanhaisilu 2023-12-08 17:50:14 +08:00
let obj = {a:1};
console.log(obj); obj.b = 2 运行一下这三句代码,看看控制台输出的对象,再把对象展开看看,就很明确了。控制台直接输出的时候,输出的引用地址的引用,展开之后能看到的是引用地址内的内容,而这个内容是可以在输出之后被修改的 |
14
minglanyu 2023-12-08 18:14:25 +08:00
console.log 的时候 targetNode 还没有被添加到 edge 上。
因为 JOSN.stringify()打印的是对象的快照而不是引用,所以 JOSN.stringify()时没有打印出结果。 但是因为 console.log 打印的是引用,所以也会打印出 TargetNode 。 可以试下用 Proxy 劫持下 edge ,当 targetNode 被添加时,打印对象。 把下面例子里的 targetObject 换成 edge 试下。 ``` const targetObject = {}; const proxy = new Proxy(targetObject, { defineProperty(target, property, descriptor) { console.log(`试图向属性 ${property} 添加值`); // 允许正常添加名为 "targetNode" 的属性 const result = Reflect.defineProperty(target, property, descriptor); // 打印被劫持对象的值和修改后的对象 console.log("被劫持对象的值:", targetObject); console.log("修改后的对象:", proxy); return result; } }); // 通过代理添加属性 proxy.targetNode = "some value"; // 试图向属性 targetNode 添加值 // 输出: 被劫持对象的值: { targetNode: 'some value' } // 输出: 修改后的对象: { targetNode: 'some value' } ``` |