javascript的传参都是引用传递。下面的代码
function mutate(obj) {
obj.a = true;
}
const obj = {a: false};
mutate(obj)
console.log(obj.a);
答案:1: prints true 2: prints false
正确答案是1.因为这里正是通过引用来传参的。
那么下面这样是否可以呢?答案已经已经可以看到了,这里的Object.assign是一种浅拷贝,对于obj里面还有嵌套的对象时,一样存在引用传递的问题
const obj = /* ... */;
const copy = Object.assign({}, obj);
function mutateDeepObject(obj) {
obj.a.thing = true;
}
const obj = {a: {thing: false}};
const copy = Object.assign({}, obj);
mutateDeepObject(copy)
console.log(obj.a.thing); // prints true
还有object.spread同样是创建一个浅拷贝
当然,有时你可能想要完全拷贝一个对象,作为参数去传递,从而不影响原有的对象。下面是介绍几种深拷贝的例子
1,json.parse
const obj = /* ... */;
const copy = JSON.parse(JSON.stringify(obj));
怎么样,可能你曾用过,这里就是深拷贝的引用。
但是对Maps, Sets, RegExps, Dates, ArrayBuffers等不适用。
- MessageChannel
function structuralClone(obj) {
return new Promise(resolve => {
const {port1, port2} = new MessageChannel();
port2.onmessage = ev => resolve(ev.data);
port1.postMessage(obj);
});
}
const obj = /* ... */;
const clone = await structuralClone(obj);
这里的消息对象 obj接收方就是一个深拷贝对象.这里是一种异步深拷贝。下面的state则是同步深拷贝的应用
3.History API
function structuralClone(obj) {
const oldState = history.state;
history.replaceState(obj, document.title);
const copy = history.state;
history.replaceState(oldState, document.title);
return copy;
}
const obj = /* ... */;
const clone = structuralClone(obj);
这里的 state每次都是一次深拷贝.(safari限制30ms内最多调用100次)
4.Notification API
function structuralClone(obj) {
return new Notification('', {data: obj, silent: true}).data;
}
const obj = /* ... */;
const clone = structuralClone(obj);
这种方式受浏览器权限限制,会比较慢。由于某些原因safari会返回 undefined
总结:实际中使用时,可以优先使用
1,JSON.parse(JSON.stringify())性能最佳且各支持种浏览器
2.MessageChanne 支持各种浏览器