DEV Community

Cover image for Advanced JavaScript Series - Part 6.2: Pass by Value & Pass by Reference, Shallow & Deep Copy, Type Coercion
Pranav
Pranav

Posted on • Updated on

Advanced JavaScript Series - Part 6.2: Pass by Value & Pass by Reference, Shallow & Deep Copy, Type Coercion

Pass by Value-

In JavaScript pass by value, the function is called by directly passing the value of the variable as the argument. Therefore, even changing the argument inside the function doesn’t affect the variable passed from outside the function.

  • It is important to note that in JavaScript, all function arguments are always passed by value. That is, JavaScript copies the values of the passing variables into arguments inside of the function.

DataTypes
Credits- Reina Mitchell

Example-

Code-

let a=5
let b=a

b++;
console.log(b)
console.log(a)
Enter fullscreen mode Exit fullscreen mode

Output-

6
5
Enter fullscreen mode Exit fullscreen mode

Pass by Reference-

In Pass by Reference, a function is called by directly passing the reference/address of the variable as the argument. Changing the argument inside the function affects the variable passed from outside the function.

  • In JavaScript, objects and arrays are always passed by reference.

Example-

Code-

let obj1={
  a: 'a',
  b: 'b',
  c: 'c'
}

// shallow copying the object using the spread operator
let obj2={...obj1}
obj2.b='d'

console.log(obj2)
console.log(obj1)
Enter fullscreen mode Exit fullscreen mode

or

let obj1={
  a: 'a',
  b: 'b',
  c: 'c'
}

// another way of copying the object
let obj2=Object.assign({}, obj1)
obj2.b='d'

console.log(obj2)
console.log(obj1)
Enter fullscreen mode Exit fullscreen mode

Output-

{
  a: "a",
  b: "d",
  c: "c"
}
{
  a: "a",
  b: "b",
  c: "c"
}
Enter fullscreen mode Exit fullscreen mode
  • But this is only a shallow copy of the original object.

A deep copy means that all of the values of the new variable are copied and disconnected from the original variable. A shallow copy means that certain (sub-)values are still connected to the original variable.

  • Lets understand this with the help of an example.

Example-

let obj1 = {
  a: 'a',
  b: 'b',
  c: {
    d: 'd'
  }
};

let obj2={...obj1}
obj2.c.d='f'

console.log(obj2)
console.log(obj1)
Enter fullscreen mode Exit fullscreen mode

Output-

{
  a: "a",
  b: "b",
  c: {
    d: "f"
  }
}
{
  a: "a",
  b: "b",
  c: {
    d: "f"
  }
}
Enter fullscreen mode Exit fullscreen mode

As you can see that the new object is still connected to the original object it got the value from.

  • The problem with shallow copy is that, if the user makes changes to the complex object (update street property of address object) of the source object userName, it is also reflected in the Destination Object, since it points to the same memory address and vice-versa.

  • Thus we turn towards Deep Copying. Deep copying means that value of the new variable is disconnected from the original variable while a shallow copy means that some values are still connected to the original variable.

  • Lets understand deep copying with the help of an example.

Example-

Code-

let obj1 = {
  a: 'a',
  b: 'b',
  c: {
    d: 'd'
  }
};

// converts obj1 to string and then parses it into a new object
let obj2 = JSON.parse(JSON.stringify(obj1))
obj2.c.d = 'f'

console.log(obj2)
console.log(obj1)
Enter fullscreen mode Exit fullscreen mode

Output-

{
  a: "a",
  b: "b",
  c: {
    d: "f"
  }
}
{
  a: "a",
  b: "b",
  c: {
    d: "d"
  }
}
Enter fullscreen mode Exit fullscreen mode
  • Here we can see that changes made in obj2 are not reflected in obj1 thus we can say that its a deep copy and the two objects are disconnected.

How to compare two objects having different memory location but same value-

  • To answer this question, I have found this Stack Overflow thread that answer this question flawlessly and I couldn't explain it any better than thus adding the link to this thread: Stack Overflow thread

  • If the link due to any reason doesn't open, here is the fastest and limited way of comparing values of objects at different memory locations-

JSON.stringify(obj1) === JSON.stringify(obj2)
Enter fullscreen mode Exit fullscreen mode

Example
Credits- Mathwarehouse


Tricky question to test knowledge-

const number = 100
const string = "Jay"
let obj1 = {
  value: "a"
}
let obj2 = {
  value: "b"
}
let obj3 = obj2;

function change(number, string, obj1, obj2) {
    number = number * 10;
    string = "Pete";
    obj1 = obj2;
    obj2.value = "c";
}

change(number, string, obj1, obj2);

// guess which variables will get updated
console.log(number); 
console.log(string);
console.log(obj1.value);
Enter fullscreen mode Exit fullscreen mode

Output-

100
Jay
a
Enter fullscreen mode Exit fullscreen mode

Type Coercion-

Type coercion is the automatic or implicit conversion of values from one data type to another (such as strings to numbers).

Table
Credits- Bill

Example-

Code-

const value1 = '5';
const value2 = 9;
let sum = value1 + value2;

console.log(sum);
Enter fullscreen mode Exit fullscreen mode

Output-

"59"
Enter fullscreen mode Exit fullscreen mode
  • In the above example, JavaScript has coerced the 9 from a number into a string and then concatenated the two values together, resulting in a string of 59. JavaScript had a choice between a string or a number and decided to use a string.

  • The compiler could have coerced the 5 into a number and returned a sum of 14, but it did not. To return this result, you'd have to explicitly convert the 5 to a number using the Number() method:

sum = Number(value1) + value2;
Enter fullscreen mode Exit fullscreen mode

As an example of type coercion in practice, look at the JavaScript Comparison Table, which shows how the loose equality == operator behaves for different types.

Implicit vs. explicit coercion

  • Type coercion can be explicit and implicit.

  • When a developer expresses the intention to convert between types by writing the appropriate code, like Number(value), it’s called explicit type coercion (or type casting).

  • Since JavaScript is a weakly-typed language, values can also be converted between different types automatically, and it is called implicit type coercion.


Connect with me-


Appendix-

  1. Advanced JavaScript Series - Part 1: Behind the scenes (JavaScript Engine, ATS, Hidden Classes, Garbage Collection)
  2. Advanced JavaScript Series - Part 2: Execution Context and Call Stack
  3. Advanced JavaScript Series - Part 3: Weird JS behavior, Strict Mode and Hoisting, Temporal Dead Zone
  4. Advanced JavaScript Series - Part 4.1: Global, Function and Block Scope, Lexical vs Dynamic Scoping
  5. Advanced JavaScript Series - Part 4.2: Scope Chains and their working, Lexical and Variable Environments
  6. Advanced JavaScript Series - Part 5: IIFE & 'this' keyword in JS(tricky Eg.), call(), apply(), bind(), Currying(Functional Prog)
  7. Advanced JavaScript Series - Part 6.1: Everything in JS is an Object? Weird JS behaviors revealed, Primitive Non-Primitive Types
  8. Advanced JavaScript Series - Part 6.2: Pass by Value & Pass by Reference, Shallow & Deep Copy, Type Coercion
  9. Advanced JavaScript Series - Part 7: First Class Citizens & Higher Order Functions
  10. Advanced JavaScript Series - Part 8: The 2 Pillars~ Closures & Prototypal Inheritance
  11. Advanced JavaScript Series - Part 9: Constructor Functions, Object Oriented, new keyword

References-

  1. https://flexiple.com/javascript-pass-by-reference-or-value/
  2. https://developer.mozilla.org/en-US/docs/Glossary/Type_coercion
  3. https://www.freecodecamp.org/news/js-type-coercion-explained-27ba3d9a2839/

Discussion (0)