Ajiu9

排除一个在开发环境下Lodash的问题

Apr 11, 2024

今天同事在开发环境运行时候,发现lodash的cloneDeep方法返回的数组对象是同一个对象,没有进行深拷贝,这种反直觉的行为必然是发生了什么。

首先我想到的是是否是全局参数配置引起的,我看了deepClone的文档,发现只有一个入参。

然后我看了下源码,也没有可以配置的参数。

import baseClone from './.internal/baseClone.js'

/** Used to compose bitmasks for cloning. */
const CLONE_DEEP_FLAG = 1
const CLONE_SYMBOLS_FLAG = 4

/**
 * This method is like `clone` except that it recursively clones `value`.
 * Object inheritance is preserved.
 *
 * @since 1.0.0
 * @category Lang
 * @param {*} value The value to recursively clone.
 * @returns {*} Returns the deep cloned value.
 * @see clone
 * @example
 *
 * const objects = [{ 'a': 1 }, { 'b': 2 }]
 *
 * const deep = cloneDeep(objects)
 * console.log(deep[0] === objects[0])
 * // => false
 */
function cloneDeep(value) {
  return baseClone(value, CLONE_DEEP_FLAG | CLONE_SYMBOLS_FLAG)
}

export default cloneDeep

没找到问题所在,我调试了下面这段代码

import { cloneDeep } from 'lodash'
const test1 = [{ id: 1, name: '测试1' }]
const deep = cloneDeep(test1)
console.log(deep[0] === test1[0]) // true

image

发现原本cloneDeep依赖了baseClone函数,但是却变成了identity这个函数就是返回函数的第一个参数。

/**
 * This method returns the first argument it receives.
 *
 * @static
 * @since 0.1.0
 * @memberOf _
 * @category Util
 * @param {*} value Any value.
 * @returns {*} Returns `value`.
 * @example
 *
 * var object = { 'a': 1 };
 *
 * console.log(_.identity(object) === object);
 * // => true
 */
function identity(value) {
  return value
}

原因找到了,是怎么引起的呢?

网上搜到了这篇文章为什么你应该立即停止使用 lodash-webpack-plugin

原来是lodash-webpack-plugin插件搞出来的。

通过用 noop、identity 或更简单的替代方案替换模块的功能集来创建更小的 Lodash 构建。该插件通过进一步缩小精选的构建来补充 babel-plugin-lodash! 在未启用适当功能集的情况下使用此插件可能会导致 lodash 函数以意想不到的方式运行。方法可能看起来有效,但它们可能返回不正确的结果,其中就包括克隆函数。

最后看了下生产构建,生产没有引用到这个插件,所以没发现影响。开发环境去掉这个插件。


>
@2024-2025 湘ICP备2024048835号