Skip to content

Instantly share code, notes, and snippets.

@JamesGelok
Forked from dalgard/extendDeep.js
Created August 4, 2021 17:11
Show Gist options
  • Select an option

  • Save JamesGelok/c1fcf86d2fc36b1bc6b9e142bc7398fe to your computer and use it in GitHub Desktop.

Select an option

Save JamesGelok/c1fcf86d2fc36b1bc6b9e142bc7398fe to your computer and use it in GitHub Desktop.
Method for deep (recursive) extension of a given object with the properties of passed-in object(s) with support for standards-compliant getters and setters
function extendDeep(target) {
// Run through rest parameters
Array.prototype.slice.call(arguments, 1).forEach(function (source) {
if (typeof target === "object") {
if (typeof source === "object") {
// If source is an array, only copy enumerable properties
var keys = (Array.isArray(source) ? Object.keys(source) : Object.getOwnPropertyNames(source));
// Iterate over keys
keys.forEach(function (key) {
// Standards-compliant awesomeness
var target_descriptor = Object.getOwnPropertyDescriptor(target, key),
source_descriptor = Object.getOwnPropertyDescriptor(source, key);
if (typeof source_descriptor.value === "object") {
if (!target_descriptor || typeof target_descriptor.value !== "object") {
target[key] = (Array.isArray(source_descriptor.value) ? [] : {});
}
// Recursion
extendDeep(target[key], source[key]);
}
else if (source_descriptor.value || source_descriptor.get || source_descriptor.set) {
Object.defineProperty(target, key, source_descriptor);
}
});
}
}
else if (typeof source !== "undefined") {
// If target is not an object, simply set it to source
target = source;
}
});
return target;
}
@JamesGelok
Copy link
Author

Ran through Prettier:

function extendDeep(target) {
  // Run through rest parameters
  Array.prototype.slice.call(arguments, 1).forEach(function (source) {
    if (typeof target === "object") {
      if (typeof source === "object") {
        // If source is an array, only copy enumerable properties
        var keys = Array.isArray(source)
          ? Object.keys(source)
          : Object.getOwnPropertyNames(source);

        // Iterate over keys
        keys.forEach(function (key) {
          // Standards-compliant awesomeness
          var target_descriptor = Object.getOwnPropertyDescriptor(target, key),
            source_descriptor = Object.getOwnPropertyDescriptor(source, key);

          if (typeof source_descriptor.value === "object") {
            if (
              !target_descriptor ||
              typeof target_descriptor.value !== "object"
            ) {
              target[key] = Array.isArray(source_descriptor.value) ? [] : {};
            }

            // Recursion
            extendDeep(target[key], source[key]);
          } else if (
            source_descriptor.value ||
            source_descriptor.get ||
            source_descriptor.set
          ) {
            Object.defineProperty(target, key, source_descriptor);
          }
        });
      }
    } else if (typeof source !== "undefined") {
      // If target is not an object, simply set it to source
      target = source;
    }
  });
  return target;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment