前不久,在开发【快捎】项目时,发现了一个Object.assign问题:
先上代码:
var config = {
token: "abcdefghijklmn",
db: 0,
retriesStrategy: {
timeout: 2500,
retries: 10,
autoload: true
}
};
//对象复制
var cfg1 = Object.assign({}, config);
var cfg2 = Object.assign({}, config);
//...
function cnt1(cfg) {
cfg.retriesStrategy.autoload = false;
//@TODO Connection to ssdb1
}
function cnt2(cfg) {
//@TODO Connection to ssdb2
}
cnt1(cfg1)
cnt2(cfg2)
上面代码中,本来定义是ssdb1是不需要主动载入的,而ssdb2则需要主动载入。按照之前的理解,使用Object.assign(obj1, obj2)的用法,应该是把obj2的成员复制到obj1中,,然后返回obj1。但答案却不是这样子,就上面的代码,造成了两个数据库都不会主动载入了。
经过一翻折腾,牺牲了本王5分钟的睡眠时间,终于把问题定位在Object.assign函数这里,以下是我的理解, 先上分析图:
9c16fdfaaf51f3de4ec91fb390eef01f3b2979ea.jpg
啊不,发错了!!嘻嘻嘻~~~
image.png
从上图结合js的对象引用特性可以看出,Object.assign只是一个浅拷贝函数,当前使用上面Object.assign({}, config)
时,仅仅是把config中第一层的对象属性copy了一份到一个空对象中,然而在原来的config对象中,有一个子对象retriesStrategy, 一直引用着自己的一块对象内存, 所以,在函数cnt1
中修复了retriesStrategy下的autoreload
属性时, 也直接修改了其引用的堆内存。当cnt2函数中使用cfg1
时,实际上是使用被修改过的retriesStrategy。
引申一下,在node.js中,数组(Array)和对象(Object)都是引用类型,以上出现的问题,在数组中同样也会出现。大家在使用时,要多多注意!!
网友评论