深拷贝浅拷贝防御性拷贝
- 开源代码
- 2025-09-12 05:21:01

这段代码是一个用于创建SQL查询参数对象(DTO)的工厂函数,主要功能是封装和管理数据库查询所需的各类参数,包括分页、排序、字段过滤等。以下是对其核心功能的逐步解析:
1. 模块导入与结构 导入依赖:引入SqlParaDTO模块,用于处理单个SQL参数。导出对象:默认导出一个包含create方法的对象,用于生成参数实例。
2. 状态初始化
每次调用create(funcSysId, jsonPara)会创建一个独立状态的参数对象:
const state = { funcSysId: String(funcSysId || ''), // 功能系统ID(强制字符串) sqlId: '', // SQL唯一标识 modelName: undefined, // 数据模型名称 queryColumn: undefined, // 查询字段过滤 sortField: undefined, // 排序字段 current: 1, // 当前页码(默认1) pageSize: 20, // 每页条数(默认20) paras: [] // SQL参数列表 }; 默认值:current和pageSize分页参数有默认值,其他字段初始为空或undefined。3. 参数合并逻辑
如果传入jsonPara对象,会覆盖state的初始值:
if (jsonPara && typeof jsonPara === 'object') { // 类型安全赋值,例如: if (jsonPara.sqlId !== undefined) state.sqlId = String(jsonPara.sqlId); if (jsonPara.current !== undefined) state.current = Number(jsonPara.current) || 0; // 浅拷贝参数数组,防止外部修改污染内部状态 if (Array.isArray(jsonPara.paras)) { state.paras = jsonPara.paras.map(p => ({ ...p })); } } 类型转换:确保数值、字符串类型正确,避免非法值。防御性拷贝:对paras数组进行浅拷贝,防止外部引用篡改。4. 公共方法集
返回的对象提供以下方法操作state:
a. 序列化方法 toJson()生成最终的JSON格式参数,仅包含有效值:
toJson() { return { funcSysId: state.funcSysId, current: state.current, pageSize: state.pageSize, ...(state.sqlId && { sqlId: state.sqlId }), // 条件包含属性 ...(state.modelName && { modelName: state.modelName }), ...(state.sortField !== undefined && { sortField: state.sortField }), ...(state.paras.length > 0 && { paras: state.paras }) // 仅非空时包含 }; } 按需包含字段:避免传递undefined或空值,减少冗余数据。 b. Setter 方法提供设置各属性的方法,如:
setCurrent(v) { const num = Number(v); state.current = isNaN(num) ? 0 : num; // 非数值设为0 } 类型安全:强制转换类型,处理非法输入。 c. 特殊参数处理 setJsonParas(json)将JSON对象转换为SqlParaDTO数组:
setJsonParas(json) { const paras = []; for (const key in json) { paras.push(SqlParaDTO.create(key, json[key])); // 使用SqlParaDTO工厂 } state.paras = paras; } 参数标准化:确保每个参数符合SqlParaDTO格式。 d. Getter 方法如getParas()返回数组副本,防止外部直接修改内部状态:
getParas() { return [...state.paras]; // 返回浅拷贝 }5. 设计意图 封装性:通过闭包隔离私有状态(state),仅暴露安全的方法。不可变性:Setter方法不直接修改外部传入的对象,而是生成新数据。数据一致性:强制类型转换和默认值确保参数合法有效。轻量传输:toJson()优化输出,省略空字段,减少网络开销。
6. 使用示例 const builder = SqlParamBuilder.create('sys_001', { current: "2" }); builder.setPageSize(50); builder.setJsonParas({ name: 'Alice', age: 30 }); console.log(builder.toJson()); // 输出: // { // funcSysId: 'sys_001', // current: 2, // pageSize: 50, // paras: [{ key: 'name', value: 'Alice' }, { key: 'age', value: 30 }] // }
7. 潜在改进点 分页默认值覆盖:若jsonPara提供无效current/pageSize,当前逻辑会覆盖默认值为0,可能导致意外行为。建议保留默认值:setCurrent(v) { const num = Number(v); state.current = isNaN(num) ? 1 : num; // 默认1而非0 } 深度拷贝:当前对paras是浅拷贝,若参数对象嵌套复杂数据,可能需要深拷贝。
总结:该代码通过工厂模式创建高内聚的参数对象,提供类型安全、数据封装和便捷的序列化功能,适用于需### 通俗解读:浅拷贝、深拷贝与防御性拷贝
一、基本概念
赋值(不是拷贝)
定义:将对象的“内存地址”直接复制给新变量,新旧变量指向同一个内存空间。风险:修改任意一方都会影响另一方,因为它们共享同一份数据。示例:let a = { name: "Alice" }; let b = a; // 赋值操作 b.name = "Bob"; console.log(a.name); // 输出 "Bob"(原数据被修改)浅拷贝
定义:仅复制对象的“第一层属性值”,如果属性是引用类型(如对象、数组),则复制其内存地址,而非实际数据。特点:新旧对象共享嵌套的引用类型数据,修改嵌套数据会互相影响。实现方式: JavaScript:Object.assign(), 扩展运算符..., Array.slice()Python:copy.copy()Java:默认的clone()方法(需类实现Cloneable接口)347 示例:let obj1 = { name: "Alice", hobbies: ["reading"] }; let obj2 = { ...obj1 }; // 浅拷贝 obj2.hobbies.push("coding"); console.log(obj1.hobbies); // ["reading", "coding"](原数据被修改)深拷贝
定义:递归复制对象的所有层级,包括嵌套的引用类型数据,新旧对象完全独立。特点:修改任意一方都不会影响另一方。实现方式: JavaScript:JSON.parse(JSON.stringify())(不支持函数、循环引用)、递归复制Python:copy.deepcopy()Java:手动实现递归clone()或使用序列化137 示例:let obj1 = { name: "Alice", hobbies: ["reading"] }; let obj2 = JSON.parse(JSON.stringify(obj1)); // 深拷贝 obj2.hobbies.push("coding"); console.log(obj1.hobbies); // ["reading"](原数据未变)二、防御性拷贝
核心目的 防止外部代码意外修改对象的内部状态,通过返回数据的副本来保护原数据。常见于封装性要求高的场景,如不可变对象、API接口设计等。
实现方式
浅拷贝防御:仅复制第一层数据。class User { constructor(data) { this.data = { ...data }; // 浅拷贝防御 } getData() { return { ...this.data }; // 返回拷贝,防止外部修改原数据 } } 深拷贝防御:复制所有层级数据,适合嵌套结构。function deepClone(obj) { return JSON.parse(JSON.stringify(obj)); // 简单深拷贝(有局限性) }应用场景
敏感数据保护:如用户信息、配置参数。多线程环境:避免共享数据导致竞态条件(如Java中的Collections.unmodifiableList())。函数参数传递:防止函数内部修改外部对象389。三、对比总结 类型数据独立性适用场景性能赋值无需要共享数据的简单场景最高(仅复制指针)浅拷贝第一层独立简单对象、无需保护嵌套数据的场景较高深拷贝完全独立复杂对象、需严格隔离数据的场景较低(递归开销)防御性拷贝按需选择封装数据、多线程、API设计取决于拷贝方式
四、通俗类比 浅拷贝:复印一本书,只复印封面,内页共用原书的纸张(修改内页内容会影响所有副本)。深拷贝:完全重印一本新书,内容和原书一样但纸张独立。防御性拷贝:图书馆借书时,给读者复印本而非原书,防止原书被涂改610。
通过合理选择拷贝方式,可以避免数据共享带来的副作用,保障程序稳定性和数据安全。要严格管理查询参数的场景。
深拷贝浅拷贝防御性拷贝由讯客互联开源代码栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“深拷贝浅拷贝防御性拷贝”
下一篇
AI编程工具-(四)