import引入的数据实际就是数据本身。
如果导出的是一个对象,该对象引入后被更改了,则会影响其他文件引入此对象
解释示例:
// resources.js
const obj = {}
export {obj}
当在a.js中import引入一个空对象obj,并且新增一个属性obj.a='a'
// a.js
import { obj } from "./resources.js";
obj.a = 'a'
console.log(obj); // {a:'a'}
那在b.js中import使用obj时,obj不再是空对象,而是obj为{a:'a'}
// b.js
import { obj } from "./resources.js";
console.log(obj); // {a:'a'}
一般情况下都不希望原始数据被更改,那应该怎么办?
解决办法1:冻结对象
// resources.js
const obj = { key: 'value' };
// 冻结对象
Object.freeze(obj);
export { obj };
Object.freeze() 冻结的特性
- 不可写:冻结对象的属性不能被修改。
- 不可扩展:不能向冻结对象添加新属性。
- 不可配置:不能删除冻结对象的属性。
- 原型不可变:冻结对象的原型不能被修改。
Object.freeze只能冻结第一层属性,如果需要冻结更深层属性则需要递归
// 递归冻结
function deepFreeze(obj) {
// 获取对象的所有属性名
const propNames = Object.getOwnPropertyNames(obj);
// 遍历所有属性,如果属性值是对象,则递归冻结
for (const name of propNames) {
const value = obj[name];
if (value && typeof value === 'object') {
deepFreeze(value);
}
}
// 冻结对象
return Object.freeze(obj);
}
判断对象是否被冻结Object.isFrozen()
const obj = { key: 'value' };
// 判断对象是否被冻结
console.log(Object.isFrozen(obj)); // 输出: false
// 冻结对象
Object.freeze(obj);
// 再次判断对象是否被冻结
console.log(Object.isFrozen(obj)); // 输出: true
解决办法2:也可以使用和vue原理相同的代理去实现。
如果确实需要更改数据,需要进行深拷贝后再进行操作
// c.js
import { arr } from "./resources.js";
import { cloneDeep } from "lodash-es";
const arrNew = cloneDeep(arr)