@performance/bad-deep-clone-check
=================================

避免使用不合理深拷贝，如JSON.parse(JSON.stringify(foo))和\_.cloneDeep(foo)。

#### 规则配置

// code-linter.json5
{
  "rules": {
    "@performance/bad-deep-clone-check": "warn",
  }
}

#### 选项

"@performance/bad-deep-clone-check": \[
      1,
      {
        "functions": \[
          "utils.clone"
        \]
      }
    \]

#### 正例

![](https://contentcenter-vali-drcn.dbankcdn.cn/pvt_2/DeveloperAlliance_scene_100_1/88/v3/UXis9mXWTiaPdQctX5tPdQ/note_3.0-zh-cn.png?HW-CC-KV=V1&HW-CC-Date=20260709T132851Z&HW-CC-Expire=86400&HW-CC-Sign=DA8A9EA3C2379891044D926136794965DC6B95FB98CD9D64DDAFDB438608F067)

正例的深拷贝实现仅作为示例，开发者需根据业务实际情况确认是否使用该实现。

*   该示例实现不支持函数和文档对象模型（Document Object Model）元素的拷贝。函数通常不需要深拷贝。
*   对于复杂的对象结构，使用该示例性能可能受到影响。
*   对于大型的自定义对象结构，可以使用结构化克隆算法（Structured Clone）或Web Worker。

// deepClone.ts
type Cloneable = object | Array<any> | Map<any, any> | Set<any> | Date | RegExp;

export function deepClone<T extends Cloneable>(source: T, weakMap = new WeakMap()): T {
  // 处理原始类型和函数
  if (typeof source !== 'object' || source === null) {
    return source;
  }
  // 处理循环引用
  if (weakMap.has(source)) {
    return weakMap.get(source);
  }
  // 处理特殊对象类型
  if (source instanceof Date) {
    return new Date(source) as T;
  }
  if (source instanceof RegExp) {
    return new RegExp(source.source, source.flags) as T;
  }
  // 处理数组
  if (Array.isArray(source)) {
    const cloneArr: any\[\] = \[\];
    weakMap.set(source, cloneArr);
    for (const item of source) {
      cloneArr.push(deepClone(item, weakMap));
    }
    return cloneArr as T;
  }
  // 处理Map
  if (source instanceof Map) {
    const cloneMap = new Map();
    weakMap.set(source, cloneMap);
    for (const \[key, value\] of source) {
      cloneMap.set(deepClone(key, weakMap), deepClone(value, weakMap));
    }
    return cloneMap as T;
  }
  // 处理Set
  if (source instanceof Set) {
    const cloneSet = new Set();
    weakMap.set(source, cloneSet);
    for (const value of source) {
      cloneSet.add(deepClone(value, weakMap));
    }
    return cloneSet as T;
  }
  // 处理普通对象
  const cloneObj = Object.create(Object.getPrototypeOf(source));
  weakMap.set(source, cloneObj);
  // 使用Object.getOwnPropertyDescriptors获取所有属性描述符
  const descriptors = Object.getOwnPropertyDescriptors(source);

  for (const \[key, descriptor\] of Object.entries(descriptors)) {
    if (descriptor.value !== undefined) {
      descriptor.value = deepClone(descriptor.value, weakMap);
    }
    Object.defineProperty(cloneObj, key, descriptor);
  }
  // 处理Symbol属性
  const symbolKeys = Object.getOwnPropertySymbols(source);
  for (const key of symbolKeys) {
    cloneObj\[key\] = deepClone(source\[key as any\], weakMap);
  }
  return cloneObj;
}

//example.ts
import { deepClone } from './deepClone';

// 使用示例
const obj = {
  a: 1,
  b: \[2, 3\],
  c: { d: 4 },
  e: new Date(),
  f: new Map(\[\['key', 'value'\]\]),
  g: new Set(\[1, 2, 3\]),
  h: /regexp/gim
};
const cloned = deepClone(obj);

#### 反例

import \_ from 'lodash';
/\*\*
\* 下载lodash依赖：
\* 1、ohpm install lodash
\* 2、ohpm install @types/lodash --save-dev
\*/
interface Foo {
id: number;
name: string;
}
const foo:Foo = {
id:1,
name:"aa"
}
const clone1:Foo = JSON.parse(JSON.stringify(foo)) as Foo;
const clone2:Foo = \_.cloneDeep(foo);

#### 规则集

plugin:@performance/recommended
plugin:@performance/all

Code Linter代码检查规则的配置指导请参考[Code Linter代码检查](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/ide-code-linter)。