@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"
]
}
]
正例
正例的深拷贝实现仅作为示例,开发者需根据业务实际情况确认是否使用该实现。
- 该示例实现不支持函数和文档对象模型(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代码检查。