JavaScript对象默认值比较疑问:为何user1==user2返回false?
问题根源
直接用user1 == user2返回false,核心原因是JavaScript里对象类型的==比较的是引用地址:只有当两个变量指向内存中同一个对象实例时,才会返回true。哪怕两个对象的结构、内容完全一模一样,只要是独立创建的不同实例,内存地址就不同,结果必然是false。
你测试的user1.toString() == user2.toString()这些场景能返回true,是因为其中一边是字符串(原始类型),此时==会触发对象的类型转换规则:把对象转成原始值(优先调用你定义的Symbol.toPrimitive方法,也就是返回name的逻辑),再比较原始值是否相等。
实现方法
JS原生的对象==/===比较逻辑是硬编码的,没法通过重写对象方法改变,要实现“两个对象默认原始值相同时返回true”的需求,有两种靠谱方式:
方式1:写个自定义比较函数(推荐)
这是最安全、可读性最高的方式,专门针对你的需求封装逻辑:
function equalByDefaultPrimitive(obj1, obj2) { // 处理null/undefined的边界情况 if (obj1 == null || obj2 == null) { return obj1 === obj2; } // 手动触发对象的原始值转换,模拟==遇到原始类型时的行为 const prim1 = obj1[Symbol.toPrimitive] ? obj1[Symbol.toPrimitive]('default') : obj1.valueOf(); const prim2 = obj2[Symbol.toPrimitive] ? obj2[Symbol.toPrimitive]('default') : obj2.valueOf(); return prim1 == prim2; } // 调用示例 console.log(equalByDefaultPrimitive(user1, user2)); // true
方式2:利用==的类型转换技巧(不推荐,可读性差)
如果你非要用==运算符,可以通过把其中一个对象转成原始类型,强制触发另一个对象的转换:
// 用String()把对象转成原始字符串,再比较 console.log(user1 == String(user2)); // true // 或者用空字符串拼接触发转换 console.log(user1 + '' == user2 + ''); // true
但这种写法比较隐晦,团队协作时容易让人困惑,不如自定义函数清晰。
避坑提醒
千万别想着去修改Object.prototype来全局改变对象的比较行为,这会污染所有对象,引发各种莫名其妙的bug。
内容的提问来源于stack exchange,提问作者Bobby Thomas
相关产品推荐
相关产品推荐

