Skip to content

Instantly share code, notes, and snippets.

@andrewchilds
Created April 28, 2022 01:07
Show Gist options
  • Save andrewchilds/f93d858d839bf40f0ebe0d2e2e9135f2 to your computer and use it in GitHub Desktop.
Save andrewchilds/f93d858d839bf40f0ebe0d2e2e9135f2 to your computer and use it in GitHub Desktop.
Simple, standalone, vanilla implementation of lodash.cloneDeep
// Simple implementation of lodash.cloneDeep
// Does not clone functions or handle recursive references.
export function deepClone(original) {
if (original instanceof RegExp) {
return new RegExp(original);
} else if (original instanceof Date) {
return new Date(original.getTime());
} else if (Array.isArray(original)) {
return original.map(deepClone);
} else if (typeof original === 'object' && original !== null) {
const clone = {};
Object.keys(original).forEach(k => {
clone[k] = deepClone(original[k]);
});
return clone;
}
return original;
}
import deepClone from './deepClone.js';
describe('deepClone', () => {
it('creates a deep clone of an object', () => {
const original = {
foo: {
a: 1,
b: new Date()
},
bar: true,
arr: ['a', 'b', { a: 9 }],
b: null,
c: undefined,
d: 123,
e: 234.56,
f: 'asdfjkh',
fn: () => { return true; },
r: /[a-z]/i,
};
const clone = deepClone(original);
expect(clone).toEqual(original);
expect(clone.foo.b).not.toBe(original.foo.b);
expect(clone.foo.b.getTime()).toBe(original.foo.b.getTime());
expect(clone.arr).not.toBe(original.arr);
expect(clone.arr).toEqual(original.arr);
expect(clone.arr[2].a).toBe(original.arr[2].a);
expect(clone.fn).toBe(original.fn);
expect(clone.r).toEqual(original.r);
expect(clone.r).not.toBe(original.r);
expect(clone.fn()).toBe(original.fn());
});
it('makes a deep clone of an array', () => {
const original = [1, 2, { a: 1, b: 2 }];
let clone = deepClone(original);
expect(clone).not.toBe(original);
expect(clone).toEqual(original);
});
it('makes a clone of an object with object references', () => {
const other = { a: 1, b: 2 };
let original = {
a: other,
b: {
a: other
}
};
const clone = deepClone(original);
expect(clone).toEqual(original);
other.a = 3;
expect(clone.a.a).toBe(1);
expect(clone.b.a.a).toBe(1);
});
it('makes a clone of a string', () => {
let original = 'hello';
const clone = deepClone(original);
expect(clone).toBe(original);
expect(clone).toEqual(original);
original = 'updated';
expect(clone).not.toBe(original);
});
it('handles undefined', () => {
const original = undefined;
const clone = deepClone(original);
expect(clone).toBe(original);
expect(clone).toEqual(original);
});
it('handles null', () => {
const original = null;
const clone = deepClone(original);
expect(clone).toBe(original);
expect(clone).toEqual(original);
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment