Languages
[Edit]
EN

JavaScript - how to clone object?

4 points
Created by:
Kate_C
19790

In JavaScript there are available few ways to clone object. In this article simple solutions how to do it has been presented.

1. Object.assign method example

This approach makes copy of first level entries.

// ONLINE-RUNNER:browser;

function cloneObject(object) {
	return Object.assign(new Object(), object);
}


// Example:

var studentObject = {
    name: 'John',
    age: 25,
    todos: [
        'Sleeping', 'Lectures', 'Classes', 'Shopping'
    ],
    action: function() { /* ... */ }
}

var studentObjectCopy = cloneObject(studentObject);

studentObject.age = 30;
studentObject.todos[0] = 'Modiffied Sleeping';

console.log(studentObject.name + ' ' + studentObject.age);
console.log(studentObject.todos);
console.log(studentObject.action);

console.log(studentObjectCopy.name + ' ' + studentObjectCopy.age);
console.log(studentObjectCopy.todos);
console.log(studentObjectCopy.action);

Note: this approach has ben introducd in ECMAScript 2015.

2. Spread syntax example

This approach makes copy of first level entries.

// ONLINE-RUNNER:browser;

var studentObject = {
    name: 'John',
    age: 25,
    todos: [
        'Sleeping', 'Lectures', 'Classes', 'Shopping'
    ],
    action: function() { /* ... */ }
}

var studentObjectCopy = { ...studentObject };

studentObject.age = 30;
studentObject.todos[0] = 'Modiffied Sleeping';

console.log(studentObject.name + ' ' + studentObject.age);
console.log(studentObject.todos);
console.log(studentObject.action);

console.log(studentObjectCopy.name + ' ' + studentObjectCopy.age);
console.log(studentObjectCopy.todos);
console.log(studentObjectCopy.action);

Note: this approach has been intorduced in ECMAScript 2018.

3. Custom clone function example

Note: read this article to know how to check types in JavaScript. 

// ONLINE-RUNNER:browser;

function getType(object) {
	return Object.prototype.toString.call(object);
}

function cloneArray(array) {
	let result = [ ];
	for (var i = 0; i < array.length; ++i) {
		result.push(cloneEntry(array[i]));
	}
	return result;	
}

function cloneObject(object) {
	let result = new Object();
	for (var property in object) {
		if (object.hasOwnProperty(property)) {
			result[property] = cloneEntry(object[property]);
		}
	}
	return result;	
}

function cloneEntry(entry) {
  	var type = getType(entry);
  
  	switch(type) {
        case '[object Array]':     return cloneArray(entry);
        case '[object Object]':    return cloneObject(entry);
        case '[object Null]':      return null;
        case '[object Undefined]': return undefined;
        case '[object Boolean]':   return Boolean(entry);
        case '[object Number]':    return Number(entry);
        case '[object BigInt]':    return BigInt(entry);
        case '[object String]':    return String(entry);
        case '[object Date]':      return new Date(entry.getTime());
        case '[object Function]':  throw new Error('Function type is not allowed.');
        default:                   throw new Error(type + ' copy operation is not supported.');
	}
}


// Example:

var studentObject = {
    name: 'John',
    age: 25,
    todos: [
        'Sleeping', 'Lectures', 'Classes', 'Shopping'
    ]
}

var studentObjectCopy = cloneEntry(studentObject);

console.log(studentObject.name + ' ' + studentObject.age 
            + ' ' + studentObject.todos);

console.log(studentObjectCopy.name + ' ' + studentObjectCopy.age 
            + ' ' + studentObjectCopy.todos);

4. Converting to JSON and back example

This approach makes deep cloning avoiding functions and added entries (properties or methods) to objects e.g. additional properties inside Array type object - some entries are still not coppied.

// ONLINE-RUNNER:browser;

function cloneObject(object) {
  	var json = JSON.stringify(object);
  
	return JSON.parse(json);
}


// Example:

var studentObject = {
    name: 'John',
    age: 25,
    todos: [
        'Sleeping', 'Lectures', 'Classes', 'Shopping'
    ],
    action: function() { /* ... */ }
}


var studentObjectCopy = cloneObject(studentObject);

studentObject.todos.property = 'This is property value';

console.log(studentObject.name + ' ' + studentObject.age);
console.log(studentObject.todos);

console.log(studentObjectCopy.name + ' ' + studentObjectCopy.age);
console.log(studentObjectCopy.todos);

console.log(studentObject.action + '  vs  ' + studentObjectCopy.action);
console.log(studentObject.todos.property + '  vs  ' + studentObjectCopy.todos.property);

5. Custom clone function vs clone with converting to JSON performance

// ONLINE-RUNNER:browser;

var count = 100000;

var studentObject = {
    name: 'John',
    age: 25,
    todos: [
        'Sleeping', 'Lectures', 'Classes', 'Shopping'
    ]
}

// Test 1: clone with converting to json

;(function() {
    function cloneObject(object) {
        var json = JSON.stringify(object);

        return JSON.parse(json);
    }
  
    var t1 = new Date();

    for(var i = 0; i < count; ++i) {
        var studentObjectCopy = cloneObject(studentObject);
    }

    var t2 = new Date();
    var dt = t2 - t1;

    console.log(dt + 'ms <- clone with converting to json');
})();

// Test 2: custom deep clone

;(function() {
    function getType(object) {
        return Object.prototype.toString.call(object);
    }

    function cloneArray(array) {
        let result = [ ];
        for (var i = 0; i < array.length; ++i) {
            result.push(cloneEntry(array[i]));
        }
        return result;	
    }

    function cloneObject(object) {
        let result = new Object();
        for (var property in object) {
            if (object.hasOwnProperty(property)) {
                result[property] = cloneEntry(object[property]);
            }
        }
        return result;	
    }

    function cloneEntry(entry) {
        var type = getType(entry);

        switch(type) {
            case '[object Array]':     return cloneArray(entry);
            case '[object Object]':    return cloneObject(entry);
            case '[object Null]':      return null;
            case '[object Undefined]': return undefined;
            case '[object Boolean]':   return Boolean(entry);
            case '[object Number]':    return Number(entry);
            case '[object BigInt]':    return BigInt(entry);
            case '[object String]':    return String(entry);
            case '[object Date]':      return Date(entry);
            case '[object Function]':  throw new Error('Function type is not allowed.');
            default:                   throw new Error(type + ' copy operation is not supported.');
        }
    }

	var t1 = new Date();

    for(var i = 0; i < count; ++i) {
        var studentObjectCopy = cloneEntry(studentObject);
    }

    var t2 = new Date();
    var dt = t2 - t1;

    console.log(dt + 'ms <- custom deep clone');
})();

 

Native Advertising
50 000 ad impressions - 449$
🚀
Get your tech brand or product in front of software developers.
For more information contact us:
Red dot
Dirask - friendly IT community for everyone.

❤️💻 🙂

Join