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

JavaScript中===严格相等的对象比较问题及语言设计疑问

嘿,这个问题问到点子上了,我来给你拆解清楚这几个核心点:

为什么值类型用===能匹配,引用类型不行?

JavaScript里的===(严格相等运算符)的行为是分类型的:

  • 对于值类型(字符串、数字、布尔值、null、undefined),它直接比较的是变量存储的实际值——只要值一样,结果就是true,这也是你测试字符串数组时符合预期的原因。
  • 对于引用类型(对象、数组、函数等),变量存储的其实是指向内存中对象实例的地址指针。===比较的就是这个指针:哪怕两个对象的内容完全一致,只要它们是内存里的两个独立实例,指针就不一样,结果自然是false。

给你举个直观的例子:

// 值类型:相同值就相等
const str1 = "apple";
const str2 = "apple";
console.log(str1 === str2); // 输出 true

// 引用类型:内容相同但内存地址不同,所以不等
const obj1 = { fruit: "apple" };
const obj2 = { fruit: "apple" };
console.log(obj1 === obj2); // 输出 false

回到你的indicesOf方法:当你在对象数组里用===匹配时,其实是在找和传入对象内存地址完全相同的元素,而不是内容相同的元素,所以才会匹配失败。

为什么JavaScript没有内置的对象深度比较运算符?

这个问题涉及到JavaScript的设计哲学和实际工程考量,主要有这几个原因:

  • 性能成本高:深度比较需要递归遍历对象的所有嵌套属性,要是对象很大或者嵌套层级深,会非常耗时。JavaScript作为一门注重运行效率的语言,不会把这种“重量级”操作内置成运算符——毕竟大部分场景下,开发者用不到深度比较,内置反而会带来不必要的性能负担。
  • 规则歧义多:深度比较的“相等”标准很难统一。比如:
    • 要不要考虑原型链上的属性?
    • 遇到循环引用的对象(比如obj.self = obj)怎么处理?
    • 日期对象和对应的字符串(比如new Date("2024-05-20")和"2024-05-20")算不算相等?
      这些问题没有标准答案,内置运算符反而会限制开发者的自定义需求。
  • 轻量化设计:JavaScript的核心设计思路是“最小核心+社区扩展”——语言本身只提供最基础、最通用的功能,复杂逻辑交给第三方库(比如Lodash的_.isEqual)或者开发者自己实现,这样能保持语言本身的轻量化和灵活性。
未来会不会加入内置的深度比较功能?

目前TC39(JavaScript的标准化委员会)有几个相关的提案正在推进,但都还处于早期阶段:

  • Record & Tuple提案:这个提案引入了不可变的引用类型,这类类型的相等性是基于内容的。比如:
    // Record是不可变对象,内容相同就相等
    const rec1 = #{ fruit: "apple" };
    const rec2 = #{ fruit: "apple" };
    console.log(rec1 === rec2); // 输出 true
    
    // Tuple是不可变数组,同理
    const tup1 = #[1, 2, 3];
    const tup2 = #[1, 2, 3];
    console.log(tup1 === tup2); // 输出 true
    
    不过这个提案还没进入正式标准,需要更多的讨论和验证。
  • 内置深度比较方法:也有提案讨论过加入类似Object.isDeepEqual()这样的内置函数,但目前还没有明确的落地时间表。

给你的临时解决方案

如果需要让你的indicesOf方法支持对象数组的内容匹配,可以自己实现一个简单的深度比较函数,替换掉===。比如这个基础版本:

function deepEqual(a, b) {
  // 先处理值类型和null/undefined的情况
  if (a === b) return true;
  // 排除非对象/数组的情况
  if (typeof a !== "object" || a === null || typeof b !== "object" || b === null) {
    return false;
  }
  // 比较属性数量是否一致
  const keysA = Object.keys(a);
  const keysB = Object.keys(b);
  if (keysA.length !== keysB.length) return false;
  // 递归比较每个属性
  for (const key of keysA) {
    if (!keysB.includes(key) || !deepEqual(a[key], b[key])) {
      return false;
    }
  }
  return true;
}

把这个函数用到你的indicesOf里,就能匹配内容相同的对象了。

内容的提问来源于stack exchange,提问作者Rick Riggs

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 09:45:38