📒
SDV503
  • SDV503
  • Command Prompt
    • Windows Command Prompt
    • Mac OS Terminal
  • GIT & GITHub
    • GitHub
    • Git
      • Git Workflow
        • Forking Workflow
  • README
    • How to write a readme.md file?
    • Write a better README.me
    • Generate a README for GitHub Repo Quickly
  • Code-comments
    • Clean Comments
    • Writing Comments in a Good way
  • Pair Coding
    • What is Pair Coding?
    • Pair Programming Experience
  • Programming?
    • What is Programming?
    • What Is A Programming Paradigm?
    • JavaScript Programming Paradigms
  • Number Systems
    • Decimal and Binary numbers
  • JavaSCript
    • Introduction To JavaScript
      • The JavaScript Engine
  • JS Call Stack
    • JavaScript call stack
    • JavaScript & Memory
      • Memory Leaks in JavaScript
    • Execution Context and Execution Stack in Javascript
      • Javascript Execution Context and Hoisting
  • JavaScript Variables
    • Introduction to JS Data Types
    • Primitive and Non-Primitive
    • Operator precedence and associativity
      • JS Operators Part One
      • JS Operators Part Two
      • JS Operators Part Three
    • Clean Code for JS Variables
  • JavaScript Scopes
    • Scope (Chain) Visualized
  • Javascript  — this keyword
  • JavaScript Data Types
    • More JavaScript Data Types
  • JavaScript Expressions and Statements
  • if/else, switch and ternary operator
    • If/Else statement
  • Switch Statement
  • Ternary Operator
  • JavaScript Loops
    • Loops in JavaScript
      • Trouble With Loops
  • Objects
    • JavaScript Objects
      • Prototypal Inheritance Visualized
      • JavaScript Number Object
      • JavaScript String Object
  • Functions
    • JavaScript Function Part One
    • JavaScript Function Part Two
    • Immediately Invoked Function Expressions ~ IIFE
    • JS => Arrow Functions
    • JavaScript Callback
    • Hoisting in JavaScript
      • Hoisting Visualized
    • Recursion Functions
    • Curry and Function Composition
  • JavaScript Features
    • JSpread Operator
    • JavaScript Built-in Functions & Objects
  • Data Structures&Algorithms
    • JavaScript’s Data Types
    • Data Structures in JavaScript
      • Introduction to Big O Notation
      • Big O Notation in Javascript
      • Linked Lists
        • Linked Lists — 2
      • Hash Tables
      • Stack & Queue
  • TLDR
    • Single quotes (‘ ’) and double quotes (“ ”) in JavaScript
  • ES6
    • Generators and Iterators
    • Javascript Classes
    • JavaScript closures
    • JavaScript Promises & Async/Await
      • Event Loop Visualized
  • C#
    • What does C#? (C Sharp)
    • C# vs JavaScript
    • What Is The Difference Between C#, .NET, ASP.NET, Microsoft.NET, and Visual Studio?
    • What is the .NET Framework?
    • Methods and Properties of Console Class in C#
    • Datatypes in C#
    • C# Code Comments
    • The if statement
    • The switch statement
    • Loops
    • Comparison operators
    • Addition assignment operators
    • The String Interpolation Operator
    • Arrays
    • Lists
    • Dictionaries
Powered by GitBook
On this page
  • What is Spread Operator?
  • Expanding Arrays or objects:
  • Arrays:
  • Objects:
  • Another Example:
  • Combining or Merging Arrays and Objects:
  • Cloning Arrays and Objects:
  • Clone array:
  • Never do the following code with cloning:
  • why?
  • Cloning with Objects:
  • Using with Math Functions
  • Accept any number of arguments in a function:
  • Some Tricks with Spread:
  • 1- First One
  • 2-Secon Trick:
  • 3- Organize Properties
  • 4-Forth Trick:
  • 5-Fifth Trick:
  • Shallow Copy & Deep Copy:
  • The problem
  • Wrong solutions
  • So How we can clone an Object with Right Way?
  • 1-Using Lodash Clone And Clonedeep
  • 2-Using immutability-helper Library:

Was this helpful?

  1. JavaScript Features

JSpread Operator

What is Spread Operator?

The JavaScript ES6 version has brought a whole array of new tools and utilities. One such new feature is the spread operator.

The operator’s shape is three consecutive dots and is written as: ...

It allows an iterable to expand in places where 0+ arguments are expected.

you can use the spread operator on Arrays and objects. you can use them in different cases: Expanding Arrays or objects, Combining or Merging Arrays and Objects, Cloning Arrays and Objects and Using with Math Functions.

Definitions are tough without context. Let’s explore some different use cases:

Expanding Arrays or objects:

Expand arrays or objects with new elements or in other names adding elements or properties to arrays or objects and operations on arrays(push-unshift):

Arrays:

Example1:

let pokemon= ['arbok','kfc','mack'];
//push
pokemon = [...pokemon,'sfdsdfs', 'tyutyu', 'bnmbn' ];
console.log(pokemon) //output: ['arbok','kfc','mack', 'sfdsdfs', 'tyutyu', 'bnmbn']
//unshift
pokemon = ['sfdsdfs', 'tyutyu', 'bnmbn', ...pokemon ];
console.log(pokemon) //output: ['sfdsdfs', 'tyutyu', 'bnmbn', 'arbok','kfc','mack']

Example2:

let arr1 = ['arbok','kfc','mack'];
let arr2 = ['sfdsdfs', 'tyutyu', 'bnmbn' ];
/*
push elements in arr2 to arr1 so the output of arr1 is ["arbok", "kfc", "mack", "sfdsdfs", "tyutyu", "bnmbn"]
*/
arr1 = [
arr1, 
arr2];
console.log({arr1, arr2});
/*
unishift elements in arr2 to arr1 so output of arr1 is ["sfdsdfs", "tyutyu", "bnmbn", "arbok", "kfc", "mack"]
*/
arr1 = [
arr2, 
arr1];

Objects:

let pickau = {name: 'pickau'};
let stats = {hp:40, attack: 60, defense: 45};
pickau = {
pickau, 
stats};
console.log(pickau)
//Output: {name: "pickau", hp: 40, attack: 60, defense: 45}
//If I did the following:
pickau = {
stats,
pickau};
console.log(pickau);
//Output: {hp: 40, attack: 60, defense: 45, name: "pickau" }

Another Example:

pickau = {
pickau, hp: 45} ;
console.log(pickau)
//Output:{ name: “pickau” , hp: 40 }

Combining or Merging Arrays and Objects:

Let’s say we have lists from two different sources and we want to combine both these sources and make a single list:

let arr1 = ['John', 'Sofia', 'Bob'];
let arr2 = ['Julia', 'Sean', 'Anthony'];
let singleList = [
arr1, 
 arr2];
console.log(singleList); //Output: [ 'Julia', 'Sean', 'Anthony', 'John', 'Sofia', 'Bob' ]
/*====================== With Objects: ======================*/
const obj1 = {name: 'john'};
const stats = {hp:40, attack: 60, defense: 45};
const obj2 = {
obj1, 
stats };
console.log(obj2) //output: {name: "john", hp: 40, attack: 60, defense: 45};

Cloning Arrays and Objects:

Clone array:

const arr = [‘1’, ‘2’, ‘3’];
const cloneArr = [
arr];
console.log(cloneArr);

Never do the following code with cloning:

const arr = [‘1’, ‘2’, ‘3’];
const cloneArr = arr;
console.log(cloneArr);

why?

Because arrays in JS are reference values, so when you try to copy it using the = it will only copy the reference to the original array and not the value of the array, so if you will do the following code:

const arr = ['1', '2'];
const arr2 = arr;
arr2.push('3');
console.log(arr2); // [ '1', '2', '3' ]  Ahhh , our original arr have changed?!
console.log(arr); // [ '1', '2', '3' ] That's why we need to clone an array:
const arr = ['1', '2'];
const arr2 = [..arr]; // Let's change our arr2 array
arr2.push('3');
console.log(arr2);// [ '1', '2', '3' ]  
console.log(arr); // [ '1', '2' ]

Cloning with Objects:

let obj = {name: 'john'};
let stats = {hp:40, attack: 60, defense: 45};
let obj2 = {...obj};
console.log(obj2) //Output: {name: "john"}
obj2 = {...stats};
console.log(obj2); //Output: {hp: 40, attack: 60, defense: 45};

Using with Math Functions

JavaScript has a Math object which contains several methods to operate with a set of data, i.e. a list of data.

Let us say we want to get the maximum value from the first three numbers of a list:

let arr = [10, 23, 83, -1, 92, -33, 76, 29, 76, 100, 644, -633];
Math.max(arr[0], arr[1], arr[2]);

What if we want to get the maximum of all numbers in a list? What if the list has n number of items? Surely we won't want arr[0], arr[1]... arr[1000].

The spread operator provides a cleaner solution:

let arr = [10, 23, 83, -1, 92, -33, 76, 29, 76, 100, 644, -633];
Math.max(...arr);

The spread operator combines well with Math.min() to find the smallest number in an array:

let arr = [10, 23, 83, -1, 92, -33, 76, 29, 76, 100, 644, -633];
Math.min(...arr);

Accept any number of arguments in a function:

If you don’t know how many arguments you need to accept in an arrow function, you can use the spread operator with the ‘rest’ parameter to make this work:

const sum = (...args) => { 
  let sum = 0;
  for(let i = 0; i < args.length; i++){
    sum += args[i];
  } 
  return sum;
};

console.log(sum(2,3)); //5
console.log(sum(2,3,4)); //9
console.log(sum(2,3,4, 5)); //14

Some Tricks with Spread:

1- First One

let greet = ['Hello', 'World'];
console.log(greet); // Without spread operator
console.log(
greet); // Using spread operator
/* If we run this code we’ll see the following:[‘Hello’, ‘World’]Hello World */

2-Secon Trick:

Sometimes, we may feel the need to convert a String into a list of characters. We can use spread operator for this use-case:

let greetings = “hello”;
let chars = [
greetings];
console.log(chars);
/*If we run this code, we’ll be greeted with:[ ‘h’, ‘e’, ‘l’, ‘l’, ‘o’ ] */

3- Organize Properties

Sometimes properties aren’t in the order we need them to be. Using a couple of tricks we can push properties to the top of the list or move them to the bottom.

To move id to the first position, add id: undefined to the new Object before spreading object.

const user1 = { password: 'Password!', name: 'Naboo', id: 300 }
const organize = object => ({ id: undefined, ...object })
console.log(organize(user1)) //Output: //=> { id: 300, password: 'Password!', name: 'Naboo' }
/*To move password to the last property, first destructe password out of object. Then set password after spreading object. */
const user2 = { password: 'Password!', name: 'Naboo', id: 300 }
const organize = ({ password, ...object }) => ({ ...object, password })
console.log(organize(user2))
//Output: //=> { name: 'Naboo', id: 300, password: 'Password!' }

4-Forth Trick:

let arr1 = [‘arbok’,’kfc’,’mack’];
let arr2 = [‘sfdsdfs’, ‘tyutyu’, ‘bnmbn’ ]
arr1 = [arr1, 
arr2];//output: [Array(3), “sfdsdfs”, “tyutyu”, “bnmbn”]
arr1 = [
arr1, arr2];//output: [“arbok”, “kfc”, “mack”, Array(3)]

5-Fifth Trick:

let obj1 = {name: ‘John’, email: ‘john@example.com’ };
let obj2 = {name: ‘Michael’, email: ‘Michael@example.com’}
obj1 = {obj1, 
obj2};
console.log(obj1)
//Output: {obj1: {
}, name: “Michael”, email: “Michael@example.com”}
obj1 = { 
obj2, obj1 };
console.log(obj1)
//output: {name: "Michael", email: "Michael@example.com", obj1: {
}}

Shallow Copy & Deep Copy:

Please note spread only goes one level deep when copying an array. So if you're trying to copy a multi-dimensional array, you will have to use other alternatives.

const arr = [ [1, 2], [10] ];
const cloneArr = [...arr];
// Let's change the first item in the first nested item in our cloned array.
cloneArr [0][0] = 'đŸ‘»';
console.log(cloneArr); // [ [ 'đŸ‘»', 2 ], [ 10 ], [ 300 ] ]
// NOOooo, the original is also affected
console.log(arr);
// [ [ 'đŸ‘»', 2 ], [ 10 ], [ 300 ] ]

Here’s an interesting thing I learned. A shallow copy means the first level is copied, deeper levels are referenced.

The problem

The spread syntax and the Object.assign() the method can only make shallow copies of objects. This means that the deeply nested values inside the copied object are put there just as a reference to the source object.

Wrong solutions

Online you will find many wrong suggestions:

  1. Using Object.create():

const copied = Object.create(original)

Here the original object is being used as the prototype of copied.

It looks fine, but under the hoods, it’s not:

const original = {
  name: 'Fiesta'
}
const copied = Object.create(original)
copied.name //Fiestaoriginal.hasOwnProperty('name') //true
copied.hasOwnProperty('name') //false

2. JSON serialization:

This only works if you do not have any inner objects and functions, but just values.

const cloned = JSON.parse(JSON.stringify(original))

But you will have the following side effects:

You will lose any JavaScript property that has no equivalent type in JSON, like Function or Infinity. Any property that’s assigned to undefined will be ignored by JSON.stringify, causing them to be missed on the cloned object.

Also, some objects are converted to strings, like Date objects for example (also, not taking into account the timezone and defaulting to UTC).

So How we can clone an Object with Right Way?

Lodash comes with two different functions that allow you to do shallow copies and deep copies. These are clone and clonedeep.

Lodash has this nice feature: you can import single functions separately in your project to reduce a lot the size of the dependency.

Take Look at the following example to understand:

const clone = require('lodash/clone'); 
const cloneDeep = require('lodash/clonedeep');

const externalObject = {
  animal: 'Cow'
};

const originalObject = {
  a: 1,
  b: 'string',
  c: false,
  d: externalObject
};

const shallowClonedObject = clone(originalObject);

externalObject.animal = 'Lion';
// The `animal` property in both the originalObject and shallowClonedObject so it is shallow copy
console.log(originalObject);
console.log(shallowClonedObject);


const deepClonedObj = clonedeep(originalObject);

externalObject.animal = 'jiraffi';
// The 'animal' property only in the originalObject changes, because it is deep clone, 
console.log(originalObject);
console.log(deepClonedObject);

2-Using immutability-helper Library:

Mutate a copy of an object without changing the original source.

Setup via NPM

npm install immutability-helper --save

We can get this library via NPM: npm install immutability-helper --save. To deep copy our object, we could use the update() method available in immutability-helper, passing the object we want to copy as the first argument and the actual data to change as the second one:

import update from 'immutability-helper';

const originalObject = {
  a: 1,
  b: 'string',
  c: false,
  d: {
    animal: 'Cow'
  }
};

const deepClonedObj  = update(originalObject, {d: {animal: 'Lion'} } );

// log the copied object to the console
console.log(deepClonedObj); // This will log animal: 'Lion', as expected

// log the source object to the console
console.log(originalObject); // This will correctly log animal: 'Cow', the original Object!
PreviousCurry and Function CompositionNextJavaScript Built-in Functions & Objects

Last updated 5 years ago

Was this helpful?

1-Using And

Lodash
Clone
Clonedeep