On This Page
Cloning Utilities
The Cloning utilities provide functions for creating copies of objects and arrays in JavaScript. These functions offer ways to create shallow or deep copies of data structures, which is crucial for avoiding unintended side effects when working with complex objects.
Functions
clone
function clone(src, options?)Creates a deep clone of the provided value.
Handling Complex Structures This function can clone arrays, objects, dates, regular expressions, maps, sets, and null-prototype objects. It uses a WeakMap internally to handle circular references and prevent infinite recursion. A class instance it does not recognise, a store, a client or a value class such as a Temporal
Instant, comes back by reference, since a walk over its properties would hand back a plain object without its prototype or its private fields.
Parameters
| Name | Type | Description |
|---|---|---|
| src | any | The value to clone |
| options | object | Optional cloning options |
Options
| Name | Type | Default | Description |
|---|---|---|---|
| preserveDOM | boolean | false |
Preserve DOM nodes by reference instead of cloning them |
| preserveNonCloneable | boolean | true |
Keep class instances by reference. false walks each into a plain object of its own properties |
Returns
A deep clone of the input value.
Example
import { clone } from '@semantic-ui/utils';
const original = { a: 1, b: { c: 2 }, d: [1, 2, 3], e: new Date(), f: /test/gi};const cloned = clone(original);
console.log(cloned); // { a: 1, b: { c: 2 }, d: [1, 2, 3], e: Date, f: /test/gi }console.log(cloned !== original); // trueconsole.log(cloned.b !== original.b); // trueconsole.log(cloned.d !== original.d); // truePreserving DOM Nodes
When preserveDOM is true, DOM nodes are kept by reference rather than deep cloned.
import { clone } from '@semantic-ui/utils';
const data = { el: document.querySelector('.my-element'), value: 42 };const cloned = clone(data, { preserveDOM: true });
console.log(cloned.el === data.el); // true (same reference)console.log(cloned.value === data.value); // trueconsole.log(cloned !== data); // trueClass Instances
A class instance is kept by reference. Settings passed to defineComponent() can carry one, a store or an API client, into the component’s data context, and a clone that walked it would hand the template a plain object with its methods and private fields gone. Pass preserveNonCloneable: false for a plain-data copy.
import { clone } from '@semantic-ui/utils';
class Store { value = 42; }const settings = { store: new Store(), config: { a: 1 } };
const cloned = clone(settings);console.log(cloned.store === settings.store); // true (same instance)console.log(cloned.config !== settings.config); // true (deep cloned)
const flattened = clone(settings, { preserveNonCloneable: false });console.log(flattened.store instanceof Store); // falseconsole.log(flattened.store); // { value: 42 }deepFreeze
function deepFreeze(value)Recursively freezes a value in place and returns the same reference. Only arrays and plain objects are walked and frozen — Date, Map, Set, RegExp, DOM nodes, and any custom class instance are left untouched so their internal slots keep working.
Loud vs silent protection Unlike
clone, which silently produces a copy,deepFreezemutates in place and throws on write in strict mode. This is the intended ergonomic — accidental writes surface as errors instead of being absorbed into a throwaway copy.
Parameters
| Name | Type | Description |
|---|---|---|
| value | any | The value to freeze. Primitives, null, and undefined are returned unchanged. |
Returns
The same reference passed in, recursively frozen. Cycles are safe (threaded WeakSet), and already-frozen inputs take a fast-path no-op.
Example
import { deepFreeze } from '@semantic-ui/utils';
const state = deepFreeze({ user: { name: 'Alice', tags: ['admin'] }, createdAt: new Date(),});
console.log(Object.isFrozen(state)); // trueconsole.log(Object.isFrozen(state.user)); // trueconsole.log(Object.isFrozen(state.user.tags)); // true
// Date/Map/Set/RegExp/DOM/class-instance values are NOT frozenconsole.log(Object.isFrozen(state.createdAt)); // falsestate.createdAt.setFullYear(2030); // still works
// Writes throw in strict modestate.user.name = 'Bob'; // TypeError: Cannot assign to read only propertyextend
function extend(obj, ...sources)Extends an object with properties from other objects, properly handling getter/setters.
Descriptor Handling This function uses
Object.getOwnPropertyDescriptorandObject.definePropertyto ensure that getters and setters are correctly copied, preserving their behavior in the extended object.
Parameters
| Name | Type | Description |
|---|---|---|
| obj | object | The target object to extend |
| sources | …object | One or more source objects |
Returns
The extended object.
Example
import { extend } from '@semantic-ui/utils';
const target = { a: 1 };const source1 = { b: 2, get c() { return this.b * 2; }};const source2 = { d: 4 };
const result = extend(target, source1, source2);console.log(result); // { a: 1, b: 2, d: 4 }console.log(result.c); // 4