Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to supply custom cloing logic #13

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

watson
Copy link

@watson watson commented Jan 14, 2015

Warning: This is a highly opinionated change so I understand if it doesn't fit the vision of this module. Also it should be released as a breaking change due to the new initializer function.

My use case is that I use deep-extend to clone MongoDB documents. They contain custom MongoDB types like Timestamp and ObjectId. This module will think they are regular object literals and extend them like any other object literal. This unfortunately means that they lose their relation to their original classes so you no longer can do an obj instanceof Klass.

This pull request adds new functionality which allows you to supply a custom cloning function which will be called for each value that deep-extend attempts to clone. If the cloning function returns a falsy value the regular behaviour of deep-extend is used, but if the cloning function returns any truthy value, that value will be used as the new value:

var Foo = function(val) {
  this.foo = val;
};
var Bar = function(val) {
  this.bar = val;
};

var cloner = function (obj) {
  // if given an instance of Foo, return a clone of it
  if (obj instanceof Foo) return new Foo(obj.foo);
};

var deepExtend = require('deep-extend')(cloner);
var obj = {
  a: new Foo(1),
  b: new Bar(2)
};

var clone = deepExtend({}, obj);

console.log(clone);
/*
{ a: { foo: 1 },
  b: { bar: 2 } }
*/
console.log(clone.a instanceof Foo); // true
console.log(clone.b instanceof Bar); // false

@watson watson force-pushed the conditional branch 2 times, most recently from 3f0710c to 8b9ebc5 Compare January 14, 2015 17:41
@unclechu
Copy link
Owner

@watson How about different interface?
May be just add some methods to main function?

Something like this?:

var deepExtend = require('deep-extend');
var customExtend = deepExtend.customExtender(cloner);

var standardCloned = deepExtend({}, obj); // standard behavior
var customCloned = customExtend({}, obj); // with custom logic

It will save backward compatibility.

@watson
Copy link
Author

watson commented Mar 29, 2015

That's not such a bad idea... you could also do it with a submodule like in is-my-json-valid:

var deepExtend = require('deep-extend');
var customExtend = require('deep-extend/custom')(cloner);

var standardCloned = deepExtend({}, obj); // standard behavior
var customCloned = customExtend({}, obj); // with custom logic

I kind of prefer the latter since adding a function to a custom property on the normal deepExtend function seems a little hack'ish. But I might be wrong.

I can update the pull request with which ever version you prefer?

@unclechu
Copy link
Owner

@watson Last version is better.

var deepExtend = require('deep-extend');
var customExtend = require('deep-extend/custom')(cloner);

@unclechu unclechu mentioned this pull request Jan 16, 2016
@unclechu unclechu self-assigned this Aug 18, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants