我们应该知道的 10 个高级 JavaScript 技巧

我们应该知道的 10 个高级 JavaScript 技巧

解构赋值

赋值解构是一种从数组或对象中提取值并将其分配给变量的简洁方法。
它简化了您的代码并提高了可读性。对于数组,可以使用括号表示法,对于对象可以使用大括号。

// 解构数组
const [firstItem, secondItem, ...rest] = [1,2,3,4,5];

console.log(firstItem);  // 1
console.log(secondItem); // 2
console.log(rest);       // [3, 4, 5]

// 解构对象
const {name, age, ...details} = {
  name: "leo",
  age: 25,
  phone: 'xxx',
  address: 'xxx'
}

console.log(name);   // leo
console.log(age);    // 25
console.log(details) // {phone: 'xxx', address: 'xxx'}

扩展语法

我们可以使用扩展语法(…)将数组的元素或对象的属性扩展到另一个数组或对象。
这对于制作副本、合并对象以及将多个参数传递给函数非常有用。

使用扩展语法生成的新对象是深拷贝,也就是改变原对象并不会影响到扩展对象

// 复制数组
const originalArray = [1,2,3];
const newArray = [...originalArray];
console.log(newArray);  // [1,2,3]

originalArray.push(4)
console.log(newArray);  // [1,2,3]

// 复制对象
const obj1 = {a: 1, b: 2};
const obj2 = {c: 3, d: 4};
const mergeObj = {...obj1, ...obj2};
console.log(mergeObj);  // {a: 1, b: 2, c: 3, d: 4}

obj1.e = 5;
console.log(mergeObj) // {a: 1, b: 2, c: 3, d: 4}

柯里化

柯里化是一种函数式编程技术,其中采用多个参数的函数被转换为一系列函数,每个函数采用单个参数。
这使得我们可以更好地重用和组合代码。

const multiply = (a) => (b) => a * b;
const multiplyByTwo = multiply(2);
const result = multiplyByTwo(5);

console.log(result) // 10

缓存

它是一种缓存技术,用于存储昂贵的函数调用的结果并避免不必要的重新计算。

它会显着降低长期递归或消耗函数的性能。

const memoizedFibonacci = (function () {
  const cache = {};
  return function fib(n) {
    if (n in cache) return cache[n];
    if (n <= 1) return n;
    cache[n] = fib(n - 1) + fib(n - 2);
    return cache[n];
  };
})();

Promise 和 ASYNC/AWAIT

Promises 和 Async/Await 对于更优雅地处理异步操作并使代码更具可读性和可维护性至关重要。
它们有助于避免地狱般的回调并改进错误处理。

function fetchData() {
  return new Promise((resolve, reject) => {
    
  })
}

async function fetchData() {
  try {
    const response = await fetch("https://xxx/data");
    const data = await response.json(0);
    return data;
  } catch (e) {
    console.error("Error fetching data:", e);
    throw e;
  }
}

闭包

闭包是捆绑在一起(封闭)的函数及其周围状态的引用的组合,闭包允许函数访问其创建时的状态
,即使该环境不再可访问。
它们对于创建私有变量和行为封装很有用。

function createCounter() {
  let count = 0;
  return function () {
    return ++count;
  };
}
const counter = createCounter();
console.log(counter()); // 1
console.log(counter()); // 2

关于闭包的两个最大的误解:

  • 闭包是一种特殊类型的函数,可以访问其周围的作用域

    这是完全错误的,原因有二:

    1. 闭包不是函数
    2. 所有函数都可以访问其周围范围*
  • 要创建闭包,我们需要嵌套函数

    同样,完全错误 - 函数嵌套是无关紧要的!每当创建一个函数时,也会创建一个关联的闭包。

函数组合

函数组合是将两个或多个函数组合起来创建新函数的过程。

它鼓励代码重用并帮助逐步创建复杂的转换。

const add = (x) => x + 1;
const multiplyByTwo = (x) => x * 2;
const compose =
  (...fns) =>
  (x) =>
    fns.reduceRight((acc, fn) => fn(acc), x);
const addAndMultiply = compose(multiplyByTwo, add);
console.log(addAndMultiply(3)); // 8

proxy

proxy对象允许我们为基本对象操作创建自定义行为。它允许我们拦截和修改对象操作。例如
访问对象属性、赋值和调用方法。

const handler = {
  get: (target, prop) => {
    console, log(`Accessing property: $(prop)`);
    return target[prop];
  },
};
const targetObj = { name: "leo", age: 25 };
const proxyobj = new Proxy(targetObj, handler);
console.log(proxyobj.name); // Accessing property: name leo :

事件委托

事件委托是一种将单个事件侦听器附加到父级而不是每个子级的多个侦听器的技术。

可以减少内存使用并提高性能,特别是对于大型列表或动态生成的内容。

document.getElementById("parent").addEventListener("click", function (event) {
  if (event.target.matches("li")) {
    console.log("You clicked on an li element!");
  }
});

Web Workers

Web Workers 允许我们在后台与主线程一起运行 JavaScript 代码。

它们对于卸载 CPU 密集型任务、避免 UI 挂起并提高性能响应能力非常有用。

// 在主线程
const worker = new Worker("worker.js");
worker.postMessage({ data: " some data" });


// 在worker.js文件
self.addEventListener("message", function (event) {
  const data = event.data; 
  const computedResult = (() => {
    // .. 复杂运算
  })()
  self.postMessage({ result: computedResult });
});