4

I have a deepClone function that I use throughout my program that clones all the properties and values of one object and returns the cloned object (see code below). I am now wanting to include an audioBuffer in the object and successfully copy it to the returning object. Is there a way to modify function to include this functionality?

TO NOTE: Not all objects passed to the deepClone function will include an audioBuffer, therefore it should be able to cope and successfully clone objects with and without them.

Edit: Can someone think of a way to combine JSON.parse(JSON.stringify(object)) with the solution provided as one of the answers? I.e. check properties of the object as the cloning is happening, if (property == 'trackBuffer') clone it differently to the rest?

deepClone function:

function deepClone (object) {
   return JSON.parse(JSON.stringify(object));
};

/**
 * Utility function for deep object cloning
 *                                                                                                                                                                               
 * @param   {object} obj  Object to be cloned
 * @returns {object}      The deep-cloned object
 */
function deepClone (object) {
    return JSON.parse(JSON.stringify(object));
};

// Create audio context
var context = new AudioContext(); 

// Create empty audio buffer
var audioBuffer = context.createBuffer(2, 22050, 44100); 

// Create object to be cloned
var track = {
  prop1: "val1",
  prop2: "val2",
  trackBuffer: audioBuffer
};

// Log before clone
console.log("before clone, track:  \n", track);

// Clone track
var clonedTrack = deepClone(track);

// Log after clone
console.log("after clone, clonedTrack: \n", clonedTrack);

As you can see from the code snippet, the clonedTrack's trackBuffer is converted to an empty object which is to be expected from JSON.parse(JSON.stringify(object));.

What is the best way to modify deepClone to successfully clone the audioBuffer but keep existing functionality?

Any help would be greatly appreciated, thanks!

Alistair Hughes
  • 387
  • 2
  • 3
  • 13

2 Answers2

5

My suggestion is that handling AudioBuffer (de)serialization as a special case is safer. When your code must work across multiple browsers and be future-proof, you're better off to use the supported APIs of the object.

function cloneAudioBuffer(fromAudioBuffer) {
  const audioBuffer = new AudioBuffer({
    length:fromAudioBuffer.length, 
    numberOfChannels:fromAudioBuffer.numberOfChannels, 
    sampleRate:fromAudioBuffer.sampleRate
  });
  for(let channelI = 0; channelI < audioBuffer.numberOfChannels; ++channelI) {
    const samples = fromAudioBuffer.getChannelData(channelI);
    audioBuffer.copyToChannel(samples, channelI);
  }
  return audioBuffer;
}
Kaiido
  • 123,334
  • 13
  • 219
  • 285
Erik Hermansen
  • 2,200
  • 3
  • 21
  • 41
0

I think below code is useful for you for cloning object.

function clone(obj) {
    if (null == obj || "object" != typeof obj) return obj;
    var copy = obj.constructor();
    for (var attr in obj) {
        if (obj.hasOwnProperty(attr)) copy[attr] = obj[attr];
    }
    return copy;
}

Please note that Answer with description is given on below link. How do I correctly clone a JavaScript object?

Community
  • 1
  • 1
Smit Shah
  • 314
  • 1
  • 3
  • 13
  • I'm afraid this is throwing the error `TypeError: Cannot set property '$__' of undefined` when calling it `Arrangement.findByIdAndUpdate(doc._id, { $set: deepClone(doc) }, function(err, result) {});` (_using mongoose driver for MongoDB_). The other suggestions on the answer you linked to throw other errors, any other modification of that function you could think of maybe? – Alistair Hughes Apr 27 '17 at 12:07
  • Are you willing to find data and update clone data MongoDB? – Smit Shah Apr 27 '17 at 12:43
  • If I'm being totally honest I am not sure what you mean by that question, sorry. Do you mean I should take out the `deepClone` function from that update statement? – Alistair Hughes Apr 27 '17 at 12:45
  • I am talking about `Arrangement.findByIdAndUpdate(doc._id, { $set: deepClone(doc) }, function(err, result) {});` are you willing to use deepClone function to clone object from mongodb and save modified object again in mongodb ? – Smit Shah Apr 27 '17 at 12:47
  • Yeah sure, I'm trying anything at the moment :) – Alistair Hughes Apr 27 '17 at 12:48
  • I had used MongoDB long ago but [this](http://masnun.com/2014/03/15/copying-duplicating-mongodb-documents-rows.html) may be useful to you.specifically for cloning – Smit Shah Apr 27 '17 at 12:59
  • On further debugging it is the line `obj.constructor()` that is causing the problem, once that is called, `copy` variable is `undefined`. When I try initialise `copy` as an empty object, I get some other errors further down the line. Any ideas? – Alistair Hughes Apr 27 '17 at 13:06