当前位置: 首页 > news >正文

深拷贝 浅拷贝防御性拷贝

这段代码是一个用于创建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参数列表
};
  • 默认值currentpageSize分页参数有默认值,其他字段初始为空或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是浅拷贝,若参数对象嵌套复杂数据,可能需要深拷贝。

总结:该代码通过工厂模式创建高内聚的参数对象,提供类型安全、数据封装和便捷的序列化功能,适用于需### 通俗解读:浅拷贝、深拷贝与防御性拷贝


一、基本概念
  1. 赋值(不是拷贝)

    • 定义:将对象的“内存地址”直接复制给新变量,新旧变量指向同一个内存空间。
    • 风险:修改任意一方都会影响另一方,因为它们共享同一份数据。
    • 示例
      let a = { name: "Alice" };
      let b = a; // 赋值操作
      b.name = "Bob"; 
      console.log(a.name); // 输出 "Bob"(原数据被修改)
      
  2. 浅拷贝

    • 定义:仅复制对象的“第一层属性值”,如果属性是引用类型(如对象、数组),则复制其内存地址,而非实际数据。
    • 特点:新旧对象共享嵌套的引用类型数据,修改嵌套数据会互相影响。
    • 实现方式
      • 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"](原数据被修改)
      
  3. 深拷贝

    • 定义:递归复制对象的所有层级,包括嵌套的引用类型数据,新旧对象完全独立。
    • 特点:修改任意一方都不会影响另一方。
    • 实现方式
      • 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"](原数据未变)
      

二、防御性拷贝
  1. 核心目的
    防止外部代码意外修改对象的内部状态,通过返回数据的副本来保护原数据。常见于封装性要求高的场景,如不可变对象、API接口设计等。

  2. 实现方式

    • 浅拷贝防御:仅复制第一层数据。
      class User {
        constructor(data) {
          this.data = { ...data }; // 浅拷贝防御
        }
        getData() {
          return { ...this.data }; // 返回拷贝,防止外部修改原数据
        }
      }
      
    • 深拷贝防御:复制所有层级数据,适合嵌套结构。
      function deepClone(obj) {
        return JSON.parse(JSON.stringify(obj)); // 简单深拷贝(有局限性)
      }
      
  3. 应用场景

    • 敏感数据保护:如用户信息、配置参数。
    • 多线程环境:避免共享数据导致竞态条件(如Java中的Collections.unmodifiableList())。
    • 函数参数传递:防止函数内部修改外部对象389。

三、对比总结
类型数据独立性适用场景性能
赋值需要共享数据的简单场景最高(仅复制指针)
浅拷贝第一层独立简单对象、无需保护嵌套数据的场景较高
深拷贝完全独立复杂对象、需严格隔离数据的场景较低(递归开销)
防御性拷贝按需选择封装数据、多线程、API设计取决于拷贝方式

四、通俗类比
  • 浅拷贝:复印一本书,只复印封面,内页共用原书的纸张(修改内页内容会影响所有副本)。
  • 深拷贝:完全重印一本新书,内容和原书一样但纸张独立。
  • 防御性拷贝:图书馆借书时,给读者复印本而非原书,防止原书被涂改610。

通过合理选择拷贝方式,可以避免数据共享带来的副作用,保障程序稳定性和数据安全。要严格管理查询参数的场景。

相关文章:

  • 每日一题洛谷普及/提高-P1154 奶牛分厩c++
  • SAP MDG —— MDG on S/4HANA 2023 FPS03 创新汇总
  • mapbox进阶,使用点类型geojson加载symbol符号图层,用于标注带图标的注记,且文字居中在图标内,图标大小自适应文字
  • html | 预览一个颜色数组
  • OpenHarmony文件管理子系统
  • Kubernetes集群部署实战:从零到英雄
  • 【Flutter】正方形的Dialog
  • 通俗易懂的聚类算法之K均值详解
  • 嵌入式开发:磁通门传感器开发(4):自然环境中的磁场
  • Pycharm配置ROS开发环境
  • 《Docker 核心概念揭秘:如何让软件开发像烹饪一样简单》
  • 【前端进阶】14 提升编程体验:组件化与模块化
  • 随机选择文件,向后写入文件内容
  • 04_DeepLearning_SVM
  • day3作业
  • 队列的顺序结构—循环队列的判断条件(rear + 1) % MAXSIZE分析
  • intra-mart实现logicDesigner与forma联动
  • AI编程工具-(四)
  • 五种经典算法路径规划—遗传算法、麻雀算法、狼群优化、粒子群算法、差分进化算法(Matlab源码)
  • IO进程线程2
  • 网页与网站的区别是什么/公司做网络推广哪个网站好
  • 做网站网页排版错误/西安高端网站建设公司
  • 永康做网站/关键词排名关键词优化
  • 动画制作app/seo优化排名教程
  • 怎样做卡盟网站/品牌宣传策略有哪些
  • wordpress 评论倒序/seo sem是指什么意思