You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何合并含Symbol的JavaScript对象?Lodash merge失效求替代方案

解决Lodash Merge无法处理Symbol类型键的问题

这个坑我之前踩过!Lodash的merge方法确实会忽略Symbol类型的对象键,因为它默认只遍历字符串键,这就导致你用Sequelize的Op(本质是Symbol)作为键的属性被丢失,最终变成空对象。下面给你几个可行的解决办法:

方法1:自定义支持Symbol键的合并函数

自己写一个递归合并函数,手动处理所有字符串键和Symbol键:

function mergeWithSymbols(target, source) {
  // 遍历源对象的所有键(字符串+Symbol)
  const allKeys = [...Object.keys(source), ...Object.getOwnPropertySymbols(source)];
  
  for (const key of allKeys) {
    const targetVal = target[key];
    const sourceVal = source[key];
    
    // 递归合并嵌套对象,否则直接覆盖
    if (typeof targetVal === 'object' && targetVal !== null && 
        typeof sourceVal === 'object' && sourceVal !== null) {
      mergeWithSymbols(targetVal, sourceVal);
    } else {
      target[key] = sourceVal;
    }
  }
  return target;
}

// 使用示例
const selectA = { where: { text: "something" } };
const selectB = { where: { date_from: { [Op.lt]: Sequelize.literal('NOW()') } } };

// 浅拷贝目标对象,避免修改原selectA
const mergedResult = mergeWithSymbols({...selectA}, selectB);
console.log(mergedResult);
// 输出:{ where: { text: 'something', date_from: { [Op.lt]: Sequelize.literal('NOW()') } } }

方法2:用Lodash的mergeWith自定义合并逻辑

Lodash其实提供了mergeWith方法,允许你自定义合并规则,我们可以利用它来处理Symbol键:

import { mergeWith } from 'lodash';
import { Op } from 'sequelize';

const selectA = { where: { text: "something" } };
const selectB = { where: { date_from: { [Op.lt]: Sequelize.literal('NOW()') } } };

const mergedResult = mergeWith({}, selectA, selectB, (objValue, srcValue) => {
  if (typeof srcValue === 'object' && srcValue !== null) {
    // 先扩展字符串键,再手动复制Symbol键
    const mergedObj = {...objValue, ...srcValue};
    for (const symKey of Object.getOwnPropertySymbols(srcValue)) {
      mergedObj[symKey] = srcValue[symKey];
    }
    return mergedObj;
  }
  // 非对象类型直接使用默认合并逻辑
});

console.log(mergedResult);

方法3:用Sequelize原生的Op.and组合条件

既然你在用Sequelize,其实可以直接用它的逻辑运算符来组合查询条件,这可能是最符合ORM设计的方式,不用自己合并对象:

import { Op } from 'sequelize';

const selectOptions = {
  where: {
    [Op.and]: [
      { text: "something" },
      { date_from: { [Op.lt]: Sequelize.literal('NOW()') } }
    ]
  }
};

为什么Lodash的merge会失效?

简单来说,Lodash内部遍历对象属性时,默认只处理可枚举的字符串键,Symbol类型的键不会被包含在默认的遍历逻辑里,所以合并时这些属性就被跳过了,最终变成空对象。

内容的提问来源于stack exchange,提问作者Andrej Leitner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 22:07:38