Skip to content

Instantly share code, notes, and snippets.

@dSalieri
Last active November 4, 2024 06:32
Show Gist options
  • Save dSalieri/97ae068448d7e9618f47dc5e2955ebea to your computer and use it in GitHub Desktop.
Save dSalieri/97ae068448d7e9618f47dc5e2955ebea to your computer and use it in GitHub Desktop.
Реализация вложенного Object.assign

Цель: Реализация вложенного присваивания, алгоритм основывается на алгоритме из спецификации Object.assign ECMAScript.

/// Демонстрация
const a = {
  a: 1, 
  b: 2, 
  c: 3, 
  obj: {
    aa: 11, 
    bb: 22, 
    cc: 33
  }
};
const b = {
  c: "3c",  
  obj: {
    cc: "33cc",
    dd: "44dd",
  }
};
deepAssign({}, a, b); /// {a: 1, b: 2, c: "3c", obj: {aa: 11, bb: 22, cc: "33cc", dd: "44dd"}}

Замечание: Данный алгоритм как и Object.assign может не создавать копии объектов.

var a = {a: 1, b: 2, c: 3};
var b = {a: 1, b: 2, c: {value: 3}};

Object.assign(a, b);
a.c === b.c /// true

var a = {a: 1, b: 2, c: 3};
var b = {a: 1, b: 2, c: {value: 3}};
createAssign(true)(a, b);
a.c === b.c /// true

var a = {a: 1, b: 2, c: 3};
var b = {a: 1, b: 2, c: {value: 3}};
createAssign()(a, b);
a.c === b.c /// false
function createAssign(instanceFlag) {
const collection = new Set();
return function assign(target, ...sources) {
let to = Object(target);
collection.add(to);
if (arguments.length === 1) return to;
for (const nextSource of sources) {
if (nextSource != null) {
let from = Object(nextSource);
let keys = Reflect.ownKeys(from);
for (const nextKey of keys) {
let desc = Reflect.getOwnPropertyDescriptor(from, nextKey);
if (desc !== undefined && desc.enumerable === true) {
let propValue = Reflect.get(from, nextKey);
/// This condition works with nested properties, its definition determine how nested properties will be recorded
switch (instanceFlag) {
case true: {
if (!(typeof to[nextKey] === "object" && to[nextKey] !== null)) break;
}
case false: {
if (!(typeof propValue === "object" && propValue !== null && !collection.has(to[nextKey]))) break;
}
default: {
propValue = assign(Array.isArray(to[nextKey]) ? [] : {}, to[nextKey], propValue);
}
}
Reflect.set(to, nextKey, propValue);
}
}
}
collection.clear();
}
return to;
};
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment