You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

请解析这段JavaScript深克隆函数clonator的实现逻辑

Breaking Down the clonator Deep Clone Function

Let's walk through this line by line to understand how it works, plus where it shines and where it falls short.

Step 1: Handle Non-Object Values

if (source === null || typeof source !== 'object') return source;

First, we check if the input is null (a quirk of JavaScript means typeof null incorrectly returns "object") or any non-object type—strings, numbers, booleans, undefined, symbols, or functions. For these values, we just return the original: primitives are copied by value automatically, and this function treats functions as "non-clonable" (since cloning functions is rarely needed and not straightforward in JS).

Step 2: Create a New Instance of the Original Object's Type

const temp = source.constructor();

This is a smart way to preserve the original object's type instead of making generic {} objects every time. Using the original's constructor creates an empty matching instance:

  • If source is an array, source.constructor is Array, so temp is a new empty array.
  • If source is a custom class instance (like new User()), temp will be a new empty User instance.
  • If source is a plain object, temp is a new empty plain object.

Step 3: Iterate Over Own Properties and Recursively Clone

for (let key in source) {
  if (Object.prototype.hasOwnProperty.call(source, key)) {
    source['isClone'] = null;
    temp[key] = clonator(source[key]);
    delete source['isClone'];
  }
}

Let's unpack this block:

  1. for (let key in source): Loops over all enumerable properties of source (including prototype chain properties, but we filter those next).
  2. Object.prototype.hasOwnProperty.call(source, key): Ensures we only clone properties that belong directly to source, not inherited from its prototype. This prevents copying things like Array.prototype.push when cloning an array.
  3. The isClone marker: This is an attempt to fix circular references (like obj.self = obj), but it doesn't work correctly. We add a temporary flag to the original object before recursion, then delete it afterward—but there's no check for this flag elsewhere in the function. If the property points back to the original object, the recursive call will still trigger infinite loops and stack overflow.
  4. temp[key] = clonator(source[key]): Recursively clones each property value and assigns it to the new instance temp.

Step 4: Return the Cloned Instance

return temp;

Finally, we send back the fully populated cloned object/array/instance.

Pros of This Function

  • Preserves the original object's type (arrays stay arrays, custom class instances stay true to their class).
  • Recursively clones nested objects and arrays.
  • Filters out inherited properties, so only own enumerable properties are copied.

Cons & Limitations

  • Circular references break it: The isClone flag doesn't actually prevent infinite recursion. Passing an object like const obj = {}; obj.self = obj will crash the function.
  • Built-in objects fail: Things like Date, RegExp, Map, or Set won't clone correctly. For example, a Date's timestamp isn't stored as an enumerable own property, so the clone will be an empty date object.
  • Non-enumerable properties are ignored: If the original object has non-enumerable own properties, they won't be copied because for...in only loops over enumerable properties.

内容的提问来源于stack exchange,提问作者Lawrence Wakefield

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 19:22:51