Vue: Duplicating an data object

Created on 25 Jun 2015  ·  18Comments  ·  Source: vuejs/vue

Hello,
in order to duplicate an object with all its children, I had to use a jQuery function, please is there a better way in Vue? I am using Vue 0.12.1

duplicateThis: function (field) {
    var currentField = this.fields[field.index];

    var insertField = {
        name: currentField.name,
        type: currentField.type,
        description: currentField.description,
        options: $.extend(true, {}, currentField.options),
        required: currentField.required
    };

    this.fields.splice(field.index + 1, 0, insertField);
}

Thank you

Most helpful comment

Have you tried JSON.parse(JSON.stringify(field))?

All 18 comments

Have you tried JSON.parse(JSON.stringify(field))?

  1. Please use https://github.com/vuejs/Discussion/issues for questions that doesn't have to do with the codebase itself;
  2. You can use the approach @Nirazul mentioned above, or use an external utility lib with a deepClone function, e.g. with underscore or lodash: _.clone(obj, true). This type of functionality does not fall within Vue's scope.
  1. Sorry.
  2. I'll try these options and was afraid to use @Nirazul's approach as it may not be working on all browsers.

Thank you both.

@FSElias
Actually, you are quite on the safe side ;)

http://caniuse.com/#search=stringify

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

@rikardocorp this only does a shallow copy, any objects within obj will be copied as references

You can try with recursive functions. I don't know how this compares in performance.

`

    var object3 = { f: 1, g: 2 };
    var object2 = { c: 1, d: 2, e: object3 };
    var object1 = { a: 1, b: object2 };
    // new object with 'copy by reference'
    var object4 = { a: 2, b: object2 }
    console.log(object1.b.c === object4.b.c); // true
    // alter one object, it alters the other (hence the copy by reference)
    object1.b.c = 2;
    console.log(object1.b.c === object4.b.c);  // true

    // Recursive function to copy objects
    function copyObject(obj){
        var nobj = {};
        for (let key in obj) {
            if (typeof obj[key] === 'object'){
                nobj[key] = copyObject(obj[key]);
            } else {
                nobj[key] = obj[key];
            }
        }
        return nobj;
    }

    // Copy object1 'by value'
    var object5 = copyObject(object1);
    object1.b.c = 3;
    // alter of object1 does not affect object5
    console.log(object1.b.c === object5.b.c)    // false

Trying several options this function has worked for me, thanks to Avijit Gupta

https://www.codementor.io/avijitgupta/deep-copying-in-js-7x6q8vh5d

function copy(o) {
   var output, v, key;
   output = Array.isArray(o) ? [] : {};
   for (key in o) {
       v = o[key];
       output[key] = (typeof v === "object") ? copy(v) : v;
   }
   return output;
}

the following works

var a = [{name: 1},{name: 2},{name: 3}];

var b = copy(a);
var c = copy(a);
b[0].name = 8;
console.log(c[0].name); // 1

Just for sharing, in some use case I need to assign callback to attribute of an object. I noticed The JSON.parse/stringify approach does not 'clone' the callback functions. I used lodash _.clone at the end.

https://stackoverflow.com/questions/36968518/typescript-json-stringify-loose-type-and-function

Trying several options this function has worked for me, thanks to Avijit Gupta

https://www.codementor.io/avijitgupta/deep-copying-in-js-7x6q8vh5d

function copy(o) {
   var output, v, key;
   output = Array.isArray(o) ? [] : {};
   for (key in o) {
       v = o[key];
       output[key] = (typeof v === "object") ? copy(v) : v;
   }
   return output;
}

the following works

var a = [{name: 1},{name: 2},{name: 3}];

var b = copy(a);
var c = copy(a);
b[0].name = 8;
console.log(c[0].name); // 1

The problem with this approach is that typeof(null) is an object, so you should be aware of that

you have to add a little line just at the beginning :
if (o === null) return null;

this solve the problem

function copy(o) {
    if (o === null) return null;

    var output, v, key;
    output = Array.isArray(o) ? [] : {};
    for (key in o) {
        v = o[key];
        output[key] = (typeof v === "object") ? copy(v) : v;
    }
    return output;
}

The problem with this approach is that typeof(null) is an object, so you should be aware of that

i add just one more if-else block, this is my code, and it's working fine

copy (o) { // copy object or array
    let output, v, key
    output = Array.isArray(o) ? [] : {}

    for (key in o) {
        v = o[key]
        if(v) {
            output[key] = (typeof v === "object") ? this.copy(v) : v
        } else {
            output[key] = v
        }
    }
    return output;
}

Copiar ArrayList:

data() {
    return {
        original: ["valor 1", "valor 2"],
        copia: []
    }
}
this.copia = JSON.parse(JSON.stringify(this.original))
console.log(this.copia) // valor 1, valor 2

@JavierSolis
It worked, thank you!

Including jQuery when you use Vue in your project should be prosecutable.

This should be straightforward and shipped with Vue.

Just to be able to cancel an editing modal with nested object structure and dates, I need to include lodash.

It have been a nightmare for me this. I couldn't duplicate a object properly keeping the functions, lodash clone and cloneDeep didn't work for me.

JSON Parse does not keep functions

I've created this function for this:

Vue.prototype.$clone = function(value) {


  if(typeof value != 'object'){

    return  value

  }

  var obj = value 
  var newObj

  if (obj instanceof Array) {
    newObj = []
  }else if(typeof obj == 'object'){
    newObj = {}
  }

  for (let k in obj) {
    let v = obj[k]

    if (obj instanceof Array) {

      newObj.push(this.$clone(v))

    } else 
    if(typeof obj === 'object'){

      newObj[k] = this.$clone(v)

    }else{
//should not arrive at this point
}

  }

  return newObj
}

Hope it helps

if you're using ES6, have you tried
const newObj = {...obj};

or something like (map, filter)

Was this page helpful?
0 / 5 - 0 ratings