Skip to content

Commit

Permalink
feat(clone): clone objects with a prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
dayongkr committed Jul 19, 2024
1 parent 6f8f500 commit 0364ec1
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 21 deletions.
61 changes: 44 additions & 17 deletions src/object/clone.spec.ts
Original file line number Diff line number Diff line change
@@ -1,52 +1,75 @@
import { describe, expect, it } from "vitest";
import { clone } from "./clone";
import { describe, expect, it } from 'vitest';
import { clone } from './clone';

describe("clone", () => {
it("should return primitive values as is", () => {
const symbol = Symbol("symbol");
describe('clone', () => {
it('should return primitive values as is', () => {
const symbol = Symbol('symbol');

expect(clone(42)).toBe(42);
expect(clone("es-toolkit")).toBe("es-toolkit");
expect(clone('es-toolkit')).toBe('es-toolkit');
expect(clone(symbol)).toBe(symbol);
expect(clone(true)).toBe(true);
expect(clone(null)).toBe(null);
expect(clone(undefined)).toBe(undefined);
});

it("should clone arrays", () => {
it('should clone arrays', () => {
const arr = [1, 2, 3];
const clonedArr = clone(arr);

expect(clonedArr).toEqual(arr);
expect(clonedArr).not.toBe(arr);
});

it("should clone objects", () => {
const obj = { a: 1, b: "es-toolkit", c: [1, 2, 3] };
it('should clone ArrayBuffer', () => {
const buffer = new ArrayBuffer(8);
const clonedBuffer = clone(buffer);

expect(clonedBuffer).toEqual(buffer);
expect(clonedBuffer).not.toBe(buffer);
});

it('should clone objects', () => {
const obj = { a: 1, b: 'es-toolkit', c: [1, 2, 3] };
const clonedObj = clone(obj);

expect(clonedObj).toEqual(obj);
expect(clonedObj).not.toBe(obj);
});

it("should clone dates", () => {
it('should clone custom objects', () => {
class CustomObject {
constructor(
public a: number,
public b: string
) {}
}

const customObj = new CustomObject(1, 'es-toolkit');
const clonedCustomObj = clone(customObj);

expect(clonedCustomObj).toEqual(customObj);
expect(clonedCustomObj).not.toBe(customObj);
});

it('should clone dates', () => {
const date = new Date();
const clonedDate = clone(date);

expect(clonedDate).toEqual(date);
expect(clonedDate).not.toBe(date);
});

it("should clone regular expressions", () => {
it('should clone regular expressions', () => {
const regex = /abc/g;
const clonedRegex = clone(regex);

expect(clonedRegex).toEqual(regex);
expect(clonedRegex).not.toBe(regex);
});

it("should shallow clone nested objects", () => {
const nestedObj = { a: [1, 2, 3], b: { c: "es-toolkit" }, d: new Date() };
it('should shallow clone nested objects', () => {
const nestedObj = { a: [1, 2, 3], b: { c: 'es-toolkit' }, d: new Date() };
const clonedNestedObj = clone(nestedObj);

expect(clonedNestedObj).toEqual(nestedObj);
Expand All @@ -55,23 +78,27 @@ describe("clone", () => {
expect(clonedNestedObj.a[2]).toEqual(nestedObj.a[2]);
});

it("should return functions as is", () => {
it('should return functions as is', () => {
const func = () => {};
const clonedFunc = clone(func);

expect(clonedFunc).toBe(func);
});

it("should clone sets", () => {
it('should clone sets', () => {
const set = new Set([1, 2, 3]);
const clonedSet = clone(set);

expect(clonedSet).toEqual(set);
expect(clonedSet).not.toBe(set);
});

it("should clone maps", () => {
const map = new Map([[1, "a"], [2, "b"], [3, "c"]]);
it('should clone maps', () => {
const map = new Map([
[1, 'a'],
[2, 'b'],
[3, 'c'],
]);
const clonedMap = clone(map);

expect(clonedMap).toEqual(map);
Expand Down
7 changes: 3 additions & 4 deletions src/object/clone.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,14 @@ export function clone<T>(obj: T): T {
return result as T;
}

if (typeof obj === "object") {
return Object.assign({}, obj) as T;
if (typeof obj === 'object') {
return Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}
return obj;
}

type Primitive = null | undefined | string | number | boolean | symbol | bigint;

function isPrimitive(value: unknown): value is Primitive {
return value == null ||
(typeof value !== "object" && typeof value !== "function");
return value == null || (typeof value !== 'object' && typeof value !== 'function');
}

0 comments on commit 0364ec1

Please sign in to comment.