How to clone object in JavaScript?

An object is an entity which has properties and types. It is a complicated datatype where it can store various data type.

const employee = {
  name:'Anna',
  id:101,
  age:35,
  salary:2000
};

In JavaScript, objects are reference values. To clone objects we cannot use assignment operator (=). Using assignment operator (=)  we are creating only an alias for existing object.

What is Shallow copy?

Shallow copy or clone copies only the actual object. Nested objects are not copied. Since mutable and stored as reference, when assigning object to another variable, we are assigning objects memory address to variable. It is a one-level deep copy.

Using Spread operator:
const employee = {
  name:'Anna',
  id:101,
  age:35,
  salary:2000
};
const empclone = {
  ...employee  // clone object using spread 
};
//changing value in employee
employee.salary=3000;
console.log(empclone);
console.log(employee);
Output:

{name:’Anna’, id:101, age:35, salary:2000}

{name: ‘Anna’, id: 101, age: 35, salary: 3000 }

Here we have created a shallow copy of object.Any change in original object is not reflected in copied object. But if object consists of nested child objects, any change in child object reflects in copied object.

Example:

const data = { name: “Anna”, age: 26, hobbies: [“Jogging”, “Tennis”, “Gym”] }

const dataCopy = { …data }

data.hobbies[0] = “Swimming”

console.log(data.hobbies)

console.log(dataCopy.hobbies)

Output:

[ ‘Swimming’, ‘Tennis’, ‘Gym’ ]

[ ‘Swimming’, ‘Tennis’, ‘Gym’ ]

Here hobbies is nested object and changing its value gets reflected in copy object.

Using Object.assign():

It is an alternative to spread operator. We can copy values and properties from one or more source object to a new object.

Syntax:
const clone = Object.assign({}, object);
Example:
const employee = {
  name:'Anna',
  id:101,
  age:35,
  salary:2000
};
const empclone = Object.assign({}, employee); // copy using Object.assign()
console.log(empclone);
Output:

{name: ‘Anna’, id: 101, age: 35, salary: 2000 }

Here the second argument employee is copied to first argument {} of assign method.

This is also shallow copy like spread operator.

Deep Copy:

In JavaScript deep copy allows us to create a completely independent copy of original object. It has the same properties but does not share the same references as original object. Any change to one object will not reflect in another object. Deep copy is performed using the methods JSON.parse() and JSON.stringify().

Using JSON.parse():
Syntax:
const clone= JSON.parse(JSON.stringify(Objname))
Example:
const employee = {
  name:'Anna',
  id:101,
  age:35,
  salary:2000
};
const empclone = JSON.parse(JSON.stringify(employee));
console.log(empclone);
Output:

{ name: ‘Anna’, id: 101, age: 35, salary: 2000 }

Example:
// Deep Clone
obj = {
  a: 1,
  b: {
    c: 1
  }
};
let cloneObj = JSON.parse(JSON.stringify(obj));
obj.a = 2;
obj.b.c = 2;
console.log(JSON.stringify(obj)); // { a: 2, b: { c: 2}}
console.log(JSON.stringify(cloneObj)); // { a: 0, b: { c: 0}}
cloneObj.a = 4;
cloneObj.b.c = 4;
console.log(JSON.stringify(obj)); // { a: 2, b: { c: 2}}
console.log(JSON.stringify(cloneObj)); // { a: 4, b: { c: 4}}
Output:

{“a”:2,”b”:{“c”:2}}

{“a”:1,”b”:{“c”:1}}

{“a”:2,”b”:{“c”:2}}

{“a”:4,”b”:{“c”:4}}

As you can see from above example that copied object is independent but it can contain incorrect values in some cases. Another drawback is it works well only with primitive datatypes like numbers, strings and Boolean.

To overcome this we have structuredClone() function.

Using structuredClone():

It creates a deep clone of an object. It overcomes many short comings of JSON.parse().

Clone inifitely nested objects and arrays.

Copy circular references.

Clone a many data types like map, set, date, RegEx, etc.,

Transfer any transferable object.

Syntax:
structuredClone(value)
structuredClone(value, options)

value – Object to clone.

Options (optional)- object with properties as follows:

transfer- An array of transferable objects that will be moved rather than cloned to the returned object.

Return value- returns a deep copy of an object.

Supported platforms:
  • Chrome 98
  • Safari 137
  • Firefox 94
  • Node.js 17.0
  • Deno 1.14

On platforms that don’t support we can use polyfills.

Example:
const employee = {
  name:'Anna',
  id:101,
  age:35,
  salary:2000
};
const empclone = structuredClone(employee);
console.log(empclone);
Output:

{name: ‘Anna’, id: 101, age: 35, salary: 2000}

Points to note:
To perform shallow copy:
  • The spread operator
  • The Object.assign() method.
To perform deep copy:
  • The JSON parsing approach
  • The structuredClone() method.

Difference-null and undefined

When writing my previous article nullish coalescing operator, i learned about the differences between null and undefined. Before that i thought both are more or less same but after getting to know about falsy values in javascript. Now i know the difference between them.

Null:

In English the literal meaning of null is having no value. null indicates the intentional absence of value in programming. null is manually assigned by programmers to variable which is declared, initialized and currently hold no value in Javascript. But a value can be expected in future. When we assign null to a variable it is empty or blank. null is of object data type in javascript. An object can be emptied by assigning it to null.

Syntax:
var a = null;

Here we have assigned value null to variable a.

undefined:

undefined means ‘not defined’. Here we declare a variable and does not assign a value to it. The value of undefined variable is set by javascript as undefined.

Syntax:
var a;

Here a variable is created at runtime and if we haven’t passed an argument for a function parameter default value is undefined. When a function doesn’t return a value it is undefined.

Similarites:

  • null and undefined denote the absence of value
  • Both are primitive Javascript types
  • They are falsy values
  • undefined and null are loosely equal (==)

null vs undefined:

Using typeof:

When we use typeof it returns object as type for null and undefined as type for undefined variable

var a = null;
console.log(typeof(a));
var b;
console.log(typeof(b));

Output:

object

undefined

Using primitive operations:

In primitive operations null is converted to 0 and undefined to NaN.

var a = 10;
var b;
var c = a+b;
console.log(c);

Output:

NaN

var a = 10;
var b = null;
var c = a+b;
console.log(c);

Output:

10

nullundefined
It is an assigned valueIt is not an assigned value
It represents an empty or unknown valueHere variable is declared but not assigned any value
It is a primitive type object in javascriptIt is a ES1 feature and is a primitive type by itself
null indicates absence of value for a variableundefined indicates absence of variable itself
Using typeof returns objectUsing typeof returns undefined
By primitive operations null is converted to zero (0)By primitive operations undefined is converted to NaN

What is the difference between data reference and object reference in SAP ABAP

PARAMETERDATAOBJECT
DEFINITIONDATA lr_ref TYPE REF TO data.DATA lr_object TYPE REF TO object.
CREATIONCREATE DATA lr_ref TYPE REF TO (‘ZIF_INSTANCE’).CREATE OBJECT lr_object TYPE (‘ZCL_CLASS’).
DEREFERENCEIt can be dereferenced. The object or any value can be assigned to dereferenced reference variable.
lr_ref->* = lr_object
Object references cannot be dereferenced. This notation
->* cannot be used.
CONVERSION OR CASTINGHow to convert a value or an object in to a reference:
it can be converted in the following two ways.
lr_ref->* = value or object
lr_ref = REF #(value/obj)
How to cast an object.
lr_object2 = CAST zcl_object2( lr_object ).
USAGEused to create data referencesUsed to create objects for classes.
ASSIGNMENTAn object or any value cannot be assigned to a data reference variable. It must be deferenced in order to assign a value.
lr_ref->* = lr_object.
lr_ref->* = ‘string_value’
Only objects can be assigned. It can be assigned directly without dereference.
DATA lr_object TYPE REF TO object.
DATA lr_object2 TYPE REF TO object.
CREATE OBJECT lr_object TYPE (‘ZCL_CLASS’).
lr_object2 = lr_object.
POSSIBLE SYNTAX ERRORAs mentioned before, values cannot be assigned directly without dereference.
For example:
lr_ref = ‘String_value’. This line of code will result in the below Error.
“The type of ‘lr_interface1’ cannot be converted to the type of ‘lr_ref’
If the types of data objects are different, then it must be casted during the assignment. Otherwise you will get the below error.
‘The type of ‘lr_object’ cannot be converted to the type of ‘lr_object2’.