高级开发人员的 JavaScript 基础知识

2025-06-07

高级开发人员的 JavaScript 基础知识

以下是我们将要深入讨论的内容

  • 提升
  • 暂时性死区
  • 函数与函数表达式之间的差异。
  • 浅拷贝与深拷贝
  • 对象分配
  • 切片与拼接
  • forEach 与 Map 对比
  • 全局执行上下文
  • 填充材料
  • 地图深度探索
  • 类型强制

1. 提升

提升是 JavaScript 中发生在执行过程中的一种行为compilation process (during lexical analysis)。在代码执行之前,JavaScript 引擎会扫描代码,并将变量和函数声明移至其各自作用域的顶部。此过程会影响变量和函数在代码中的访问方式和时间。

  • Var 被提升并用未定义初始化。
console.log(a) // undefined
var a = 10;
Enter fullscreen mode Exit fullscreen mode
  • Let 和 Const 被提升但未被初始化。
console.log(a) // Reference Error , Temporal Dead Zone.
let a = 10;
Enter fullscreen mode Exit fullscreen mode
  • 函数声明被提升,我们可以在代码中的任何地方访问它们。
console.log(getNum());
function getNum(){
    return 2*2;
}
Enter fullscreen mode Exit fullscreen mode
  • 函数表达式未完全提升
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

上面只有变量被提升,而不是函数。

2. 暂时性盲区

它是从范围/块开始到变量被定义和初始化之间的一段时间。

什么时候发生?

  • 仅存在于用 let 和 const 声明的变量中。
  • 它基本上可以防止在初始化之前访问它们。
  • 访问 TDZ 中的变量会导致 ReferenceError。
  • TDZ 也适用于分配给 let 和 const 的函数表达式。

JavaScript

3. 函数 Dec 与函数表达式

函数定义:用 function 关键字定义的函数。

  • 它们被吊起来了。
  • 可在整个范围内访问。

函数表达式:当将函数分配给变量时。

  • 未提升
  • 声明后才可用

当你需要函数在作用域内的任何位置都能访问时,可以使用函数声明。

使用函数表达式可以更好地控制函数的使用时间和位置。

4.浅拷贝与深拷贝

浅拷贝:仅复制顶层属性,对于嵌套对象,传递引用。

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

进行浅拷贝的其他方法

  • Object.assign()
  • Spread Operator
  • Slice Operator[如果存在嵌套对象,新数组将包含引用]
  • Concat Operator

深度复制:它复制了所有属性。

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

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

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

如果我们使用上述方法,我们可能会遇到这些问题

  • 它无法处理未定义的函数。
  • 这需要时间,因为我们正在进行序列化和反序列化。

进行深度复制的其他方法

  • structuredClone()- 这是一种 JS 方法,用于深度克隆。
let obj1 = { name: "Jayant", address: { city: "Delhi" } };
// It addresses most of the JSON method's shortcoming.
let obj2 = structuredClone(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
  • Recursive based custom deep copy function

5.Object.assign()

它是一个 JS 方法,用于将属性从一个或多个对象复制到其他对象

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 用于提取数组的部分内容,

Slice makes shallow copy

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 与 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 循环

8.执行上下文

它是代码执行的环境。

它有两种类型:

1) Global EC
2)Function EC

Global EC- 它是 JS 文件运行时第一个运行的 EC。
它包含全局变量、函数和词法环境。程序停止时,它会被移除。

9. 填充材料

这是一种编写代码的行为,使旧浏览器兼容新功能。

较旧的浏览器(例如 Internet Explorer)不支持 Array.includes()。
为了添加此功能,我们可以编写一个 polyfill。

Array.includes() 的 Polyfill

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

10、地图深度探索

通常我们只向回调函数传递 1 个参数,
但在内部,map() 为回调函数提供了 4 个参数

// 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

如果您想在稀疏数组的情况下给出默认值而不是空值,您可以借助 forEach 或扩展运算符或使用 map 进行过滤来实现。

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 forEeach also || filter with map.
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]

// using arr.filter(Boolean).map
// Boolean is a built in function that converts values to true or false.
// If the value is truthy, it stays in the array; if falsy, it gets removed.
arr.filter(Boolean).map((item)=>item*2);
Enter fullscreen mode Exit fullscreen mode

map() Sets the Range of Elements Before Execution:表示在第一次回调执行之前确定正在由回调处理的元素。

  • 执行期间添加到数组的新元素将被忽略。
  • 处理之前删除的元素将被跳过。

11. 类型强制

自动从一种数据类型转换为另一种数据类型。

它以三种方式发生:

隐式强制→JS 自动转换类型。

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

显式强制转换 → 我们使用函数手动转换类型。

抽象操作 → JS 中类型转换的内部规则。

文章来源:https://dev.to/jay818/javascript-basics-for-a-senior-dev-1lob
PREV
React 组件生命周期
NEXT
React Context,一体化