Lodash 用法(含深度克隆)

lodash.min.js 是 Lodash 库的一个压缩版本,它提供了一系列强大的工具函数,用于处理数组、数字、对象、字符串、等数据类型。Lodash 的 API 设计得非常一致,所以一旦你掌握了一些基本的使用方法,你就可以轻松地应用到其他函数上。

以下是一些基本的 Lodash 函数使用示例:

引入 Lodash

在 HTML 中,你可以通过 <script> 标签引入 lodash.min.js

<script src="https://cdn.jsdelivr.net/npm/lodash@4.17.21/lodash.min.js"></script>

在 JavaScript 模块中,如果你使用的是 npm 或 yarn 进行包管理,你可以这样引入 Lodash:

const _ = require('lodash');
// 或者在支持 ES6 模块的环境中
import _ from 'lodash';

使用 Lodash

一旦 Lodash 被引入,你就可以使用 _ 符号来访问所有的 Lodash 方法了。

数组操作

// _.chunk - 将数组分割成多个指定大小的小数组
const array = [1, 2, 3, 4, 5, 6];
console.log(_.chunk(array, 2)); // => [[1, 2], [3, 4], [5, 6]]

// _.uniq - 创建一个去重后的数组
const duplicateArray = [1, 2, 2, 3, 4, 4];
console.log(_.uniq(duplicateArray)); // => [1, 2, 3, 4]

对象操作

// _.get - 安全地读取对象的嵌套属性
const object = { a: { b: { c: 1 } } };
console.log(_.get(object, 'a.b.c')); // => 1
console.log(_.get(object, ['a', 'b', 'c'])); // => 1
console.log(_.get(object, 'a.b.c.d', 'default')); // => 'default'

// _.set - 安全地设置对象的嵌套属性
_.set(object, 'a.b.c', 2);
console.log(object.a.b.c); // => 2

集合操作

// _.map - 遍历集合中的每个元素,并应用提供的函数
const users = [{ 'user': 'barney' }, { 'user': 'fred' }];
const names = _.map(users, (user) => user.user);
console.log(names); // => ['barney', 'fred']

// _.filter - 过滤集合中的元素,只保留那些符合条件的元素
const numbers = [1, 2, 3, 4, 5, 6];
const evenNumbers = _.filter(numbers, (n) => n % 2 === 0);
console.log(evenNumbers); // => [2, 4, 6]

函数操作

// _.debounce - 创建一个防抖动函数,该函数会延迟调用提供的函数直到等待时间结束
const debouncedFunction = _.debounce(() => {
  // 这个函数会在最后一次调用后的 200ms 后执行
}, 200);

window.addEventListener('resize', debouncedFunction);

// _.throttle - 创建一个节流函数,该函数在每个等待时间内最多调用一次提供的函数
const throttledFunction = _.throttle(() => {
  // 这个函数不会频繁地调用,而是每 200ms 最多调用一次
}, 200);

window.addEventListener('scroll', throttledFunction);

在编程中,深度克隆(deep cloning)指的是创建一个对象的副本,并且递归地复制它的所有属性,包括所有的子对象。这样做的结果是,副本和原始对象在内存中是完全独立的,对副本的修改不会影响到原始对象。

在 JavaScript 中,可以使用不同的方法来实现深度克隆:

使用 Lodash 的 _.cloneDeep 方法

Lodash 是一个流行的 JavaScript 实用工具库,它提供了一个名为 _.cloneDeep 的方法来执行深度克隆。这是一个简单且可靠的方法,尤其是对于复杂的对象结构。

const _ = require('lodash');

const object = {
  a: 1,
  b: {
    c: 2,
    d: [3, 4],
  },
};

const deepClone = _.cloneDeep(object);
console.log(deepClone); // { a: 1, b: { c: 2, d: [3, 4] } }

使用 JSON 方法

对于不包含函数、undefined 和循环引用的简单对象,你可以使用 JSON 方法来实现深度克隆:

const object = {
  a: 1,
  b: {
    c: 2,
    d: [3, 4],
  },
};

const deepClone = JSON.parse(JSON.stringify(object));
console.log(deepClone); // { a: 1, b: { c: 2, d: [3, 4] } }

但是,这种方法有几个限制:

  • 无法复制函数。
  • 无法复制 undefined,它会在序列化时被忽略。
  • 无法复制循环引用的对象,这会导致 JSON.stringify 抛出错误。
  • 无法复制特殊对象,如 MapSetDateRegExp 等,它们会被转换成普通对象或丢失信息。

手动实现深度克隆

如果你不想使用外部库,并且需要处理复杂的对象(例如包含函数、特殊对象等),你可以编写自己的深度克隆函数。这通常涉及到递归和类型检查:

function deepClone(obj, hash = new WeakMap()) {
  if (obj === null) return null;
  if (obj instanceof Date) return new Date(obj);
  if (obj instanceof RegExp) return new RegExp(obj);
  if (typeof obj !== 'object') return obj;
  if (hash.has(obj)) return hash.get(obj); // 循环引用处理

  const clone = Array.isArray(obj) ? [] : {};
  hash.set(obj, clone);

  Object.keys(obj).forEach(
    key => (clone[key] = deepClone(obj[key], hash))
  );

  return clone;
}

const object = {
  a: 1,
  b: {
    c: 2,
    d: [3, 4],
  },
};

const deepClone = deepClone(object);
console.log(deepClone); // { a: 1, b: { c: 2, d: [3, 4] } }