DEV Community

Cover image for JavaScript Basics for a Senior Dev
Jayant
Jayant

Posted on

97 4 4 5 5

JavaScript Basics for a Senior Dev

Here are the thing we are goona talk about in depth

  • Hoisting
  • Temporal Dead Zone
  • Diff b/w Function & Function Exp.
  • Shallow Copy vs Deep Copy
  • Object.assign
  • Slice vs Splice
  • forEach vs Map
  • Global Execution Context
  • Polyfilling
  • Map Deep Dive
  • Type Coercion

1. Hoisting

It is a JS Mechanism in which variable and function declartions are moved to the top of their scope before the code is executed.

  • Var is Hoisted and Initialized with undefined.
console.log(a) // undefined
var a = 10;
Enter fullscreen mode Exit fullscreen mode
  • Let and Const are Hoisted but not Initialized.
console.log(a) // Reference Error , Temporal Dead Zone.
let a = 10;
Enter fullscreen mode Exit fullscreen mode
  • Function Declartion are hoisted,we can access them any where in the code.
console.log(getNum());
function getNum(){
    return 2*2;
}
Enter fullscreen mode Exit fullscreen mode
  • Function Expression are not fully Hoisted.
console.log(getNum()); // ReferenceError, getNum2 is not defined : Same for let , TDZ
const getNum =()=>{
    return 2*2;
}


console.log(getNum4()); // TypeError: getNum4 is not a function
var getNum4 =()=>{
    return 2*2;
}
Enter fullscreen mode Exit fullscreen mode

Above only the variable is hoisted not the function.

2. Temporal dead zone

It is a period between start of the scope/block till the variable is defined and initialized.

When it occurs?

  • Only Exists for variable that are decalred with let and const.
  • It basically prevents them from being accessed before initialization.
  • Accessing a variable in TDZ results in a ReferenceError.
  • TDZ applies to function expressions assigned to let and const as well.

Javascript

3. Function Dec Vs Function Expression

Function Dec. : Function defined with function keyword.

  • They are Hoisted.
  • Accessible in the entire scope.

Function Exp. : when a function is assigned to a variable.

  • Not Hoisted
  • Available only after declaration

Use function declarations when you need a function to be accessible anywhere in the scope.

Use function expressions for more control over when and where a function is used.

4. Shallow Copy Vs Deep Copy

Shallow Copy : Copies the top level properties only,For Nested Objects reference is passed.

let obj1 = { name: "Jayant", address: { city: "Delhi" } };
let obj2 = {...obj1};

obj2.address.city = "Gurugram";

console.log(obj1);
console.log(obj2);

// Both prints the same output 
// {
//     "name": "Jayant",
//     "address": {
//         "city": "Gurugram"
//     }
// }
Enter fullscreen mode Exit fullscreen mode

Other ways to make shallow copy

  • Object.assign()
  • Spread Operator
  • Slice Operator [ New array will contain refernce in case of nested object ]
  • Concat Operator

Deep Copy : It Copied all the properties.

let obj1 = { name: "Jayant", address: { city: "Delhi" } };

// Creating a deep copy
let obj2 = JSON.parse(JSON.stringify(obj1));

obj2.address.city = "Mumbai"; // βœ… Changes only obj2

console.log(obj1); // { name: "Jayant", address: { city: "Delhi" } }
console.log(obj2); // { name: "Jayant", address: { city: "Mumbai" } }
Enter fullscreen mode Exit fullscreen mode

Other ways to make shallow copy

  • Recursive based custom deep copy function

5. Object.assign()

It is an JS method that is used to copy properties from one or more object to other

We can do the same thing using Spread Operator.

// Syntax : Creates Shallow Copy
Object.assign(<target>,..sources)

// Example 
let obj1 = {
    name:"Jayant"
}

let obj2 = {
    status:"single"
}
// If two objects have the same property, the last object's value will overwrite previous values.
let obj3 = Object.assign({},obj1,obj2);
Enter fullscreen mode Exit fullscreen mode

6. Slice Vs Splice

Slice is used to extract parts of the array

Slice makes shallow copy

Splice is used to add/remove elements from the array


Slice vs Splice

// Slice : arr.slice(start,end);
// end is exclusive, include nhi hoga
const arr = [1,2,3,4,45,5,6,7];
const newArray = arr.slice(1,4); 
console.log(newArray); // [2,3,4 ]

console.log(arr.slice(-2)); // [6,7] , get last 2 elemnets 


// Splice : arr.splice(start,deleteCount,...items);

const itemsToAdd = [2,3,4,5,6,7];
const newArr = [1,2,3,4,45,5,6,7];
console.log(newArr.splice(1,7,...itemsToAdd)); //[2,3,4,45,5,6,7]
console.log(newArr); // [1,2,3,4,5,6,7];

const newArr2 = [1,2,3,4,45,5,6,7];
console.log(newArr2.splice(-2));  // [6,7] // removed last 2 elements
console.log(newArr2); // [1,2,3,4,45,5]
Enter fullscreen mode Exit fullscreen mode

7. ForEach Vs Map

ForEach and Map doesn't support early return, if you want to return early return you can use some,every,reduce,for of loop.

[1,2,3,4,5,,6,7].forEach((el)=>{
    if(!el){
        break;  // Gives Error, Same for Map
    }
    console.log(el)
})
Enter fullscreen mode Exit fullscreen mode

ForEach Loop

8.Execution Context

It is an Environment where code is executed.

It is of 2 Types:

1) Global EC
2) Function EC

Global EC - It is the first EC that runs when JS file runs.
It contains global variable and functions,Lexical Environmet. It is removed when program stops.

9. Polyfilling

It is an act of writing code that make old browser compaitable of newer features.

Older browsers (like Internet Explorer) do not support Array.includes().
To add this functionality, we can write a polyfill.

Polyfill for Array.includes()

if (!Array.prototype.includes) {
  Array.prototype.includes = function (element) {
    return this.indexOf(element) !== -1;
  };
}
Enter fullscreen mode Exit fullscreen mode

10, Map Deep Dive

Generally we pass only 1 argument to the Callback
But internally, map() provides 4 arguments to the callback function

// array is accessible in case of forEach also
arr.map((value,index,array,this)=>{})

const arr = [1,2,3,4,5,,65];

console.log(arr.map((val)=>{
    console.log(arr[0]);
    return val;
}));   // arr is already available in the scope so what is the need of it?
// the third optional argument can be useful when we don't have access to it.

// For Example in a Function 
function processData(arr) {
    return arr.map((val, index, array) => {
        console.log(array[0]); // Accessing the first element dynamically
        return val * 2;
    });
}

console.log(processData([10, 20, 30]));

Enter fullscreen mode Exit fullscreen mode

Sparse Array - Array with missing elements

const arr = [1,2,,5,6,,7,8,9] // Sparse Array 

// By default map skips this and doesn't call the callback function for them.
// the empty slots remains in the array

console.log(arr.map((val)=>{
    if(!val){
        return 0;
    }
    return val*2
})) // [2, 4, 6, 8, 10, empty, 130]
Enter fullscreen mode Exit fullscreen mode

if you want to give a default value instead of the empty value in case of sparse array, you can do this with the help of 3forEach or spread operator.

const arr = [1,2,,5,6,,7,8,9];

// using spread operator converts a sparse array into a dense one with explicit undefined values || use can use forEcah also.
console.log([...arr].map((val,index,arr)=>{
    if(!val){
        return arr[index-1] || 0;
    }
    return val*2
}))  // [2, 4, 2, 10, 12, 6, 14, 16, 18]
Enter fullscreen mode Exit fullscreen mode

map() Sets the Range of Elements Before Execution : Means Elements that are being processed by the callback are determined before the first callback execution.

  • New elements added to the array during execution are ignored.
  • Deleted elements before being processed are skipped.

11. Type coercion

Automatic conversion from one data type to another.

It happens in three ways:

Implicit Coercion β†’ JS automatically converts types.

console.log(10+"2"); // [Concatation]
console.log(10-"2"); // [conversion] - To number
console.log(10*"2"); // [conversion] - To number
console.log(10/"2"); // [conversion] - To number

console.log(true+1) // true converted to number gives 1
// false -> 0

console.log(null+undefined) // NaN
// null -> 0 
// undefined -> NaN

console.log(null + 10);      // 10  (null β†’ 0)
console.log(undefined + 10); // NaN (undefined β†’ NaN)

const obj = { name: "John" };

console.log(String(obj)); // "[object Object]"
console.log(obj + "");    // "[object Object]"

// [] -> ""
console.log([] + 2); // "2" (Array β†’ Empty String β†’ Concatenation)
console.log([] - 2); // -2 (Array β†’ Empty String β†’ 0 - 2 = -2)

console.log([1] + [2]); // "12"




Enter fullscreen mode Exit fullscreen mode

Explicit Coercion β†’ We manually convert types using functions.

Abstract Operations β†’ Internal rules for type conversion in JS.

Top comments (11)

Collapse
 
skamansam profile image
Samuel β€’

You really need to mention structuredClone() as a way to deep copy. It is builtin and requires much less processing than json conversion. It also derefs pointers in a much better way. IMO, it's the best way to deep copy.

Collapse
 
jay818 profile image
Jayant β€’

Pls share your opinion here

Collapse
 
tbogard profile image
Erick Rodriguez β€’

I think you need to go beyond map and include filter when sparced elements of an array might include falsy values sucn as null or indefined. You would save ton of time by using array.filter(Boolean).map(...) to assert right data.

Actually I was expecting Proxy object, hashmaps with tiny pointers, and Observables new patterns In this article. Not bad for the first suggestions.

Collapse
 
julius_koronci_f8b2a9766d profile image
Julius Koronci β€’

Seems the author doesn't know the difference between what is hoisting and how it looks like, yes the effect is similar to what's described but that's really not what hoisting is about.. hoisting is about how js is compiled and yes it's a compiled language and hoisting is a result or way of how lexing is being done

Collapse
 
deathcrafter profile image
Shaktijeet Sahoo β€’

JSON is not the way to deep copy. Yes, it covers basic data types, but you lose any class objects or types that are not supported by JSON. I know you are just providing an example, but you should explicitly mention this as it is a bad habit.

IMO deep copying something you don't know the shape of is a bad habit by default. If required, you should create a function that takes in the object you need and makes a deep copy of it.

Collapse
 
juni0r profile image
Andreas Korth β€’ β€’ Edited

Our senior devs spend way too much of their time hoisting and polyfilling. I always found their copies to be way too shallow, especially if you consider how much we pay them. Reading this article really stepped up their game.

Collapse
 
aniruddhaadak profile image
ANIRUDDHA ADAK β€’

What a great read! Thank you for your insights! 🌼

Collapse
 
tehmoth profile image
tehmoth β€’

should probably mention that let and const have a different scope (block scope) than var (function scope)

Collapse
 
avelino_nogueira_2f1e3513 profile image
Avelino Nogueira β€’

If your senior js developer needs this article to improve programming you need to talk to HR to do better interviews.... Some of this stuff are basic and incorrect.

Collapse
 
chibu profile image
Chibuike Maduabuchi β€’

Top notch

πŸ‘‹ Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay