我的问题本身是这样的:
应该如何正确比较两个对象
javascript
?
$(document).ready(function(){
function p(o){
return JSON.stringify(o)
}
function compare(o1, o2){
const r = (o1 === o2)
console.log(p(o1) + ' === ' + p(o2) + ': ' + r)
}
var a = [], b = [], c = a;
var x = {}, y = {}, z = x;
compare(a, b) // false
compare(a, c) // true
compare([], []) // false
compare({}, {}) // false
compare(99, 99) // true
compare(new Number(1), 1) // false
compare(new Number(1), new Number(1)) // false
compare(new String('o'), new String('o')) // false
compare(new String('s'), 's') // true
compare('foo', 'foo') // true
compare({'foo':'bar'}, {'foo':'bar'}) // false
compare(x, y) // false
compare(x, z) // true
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
我很清楚,在前面的代码片段中,原始objetos
类型正确返回:true
console.log((9 === 9)) // true
但我想知道,除了知道如何正确比较两个对象之外,为什么会发生这种情况......
console.log(([] === [])) // false
更新:
排除了对象的比较JSON.stringify()
,在下面的例子中你可以看到这两个对象是一样的,它们唯一的变化是元素的位置,所以比较它们时会返回false
:
var a = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
var b = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
console.log(a === b); // true
var x = JSON.stringify({
"firstName": "JP",
"lastName": "Richardson"
});
var y = JSON.stringify({
"lastName": "Richardson",
"firstName": "JP"
});
console.log(x === y); // false
直接响应
比较两个对象是否是“孪生”,首先判断它们是否是同一个“父”的“子”,然后判断它们是否具有相同的“DNA”,即对象是同一个对象的实例,属性是同一个对象的实例。相同(名称、顺序、属性和值)。
如果您对它们是“双胞胎”不感兴趣,但只有某些项目相同,请比较这些项目。
下面是一个关于如何知道两个对象是否是同一个对象的实例的简短示例,为简洁起见,它们是否具有相同的属性,这意味着它们的属性具有相同的名称并且它们的位置相同。
解释
比较的“必须”是由目的来说明的,在 JavaScript 的情况下更是如此。
与其他编程语言相比,JavaScript 可以被认为非常灵活,因为执行操作的算法考虑了操作数的类型。
在 JavaScript 中实现比较时,考虑到上述情况,我们必须牢记:
考虑到上述情况以及作为一门灵活语言的前提,JavaScript 包含两种比较类型,严格比较和抽象比较,每种比较都有自己的算法,在 ECMAScript 规范中有描述。以下是第 5 版相应部分的链接。
总之
两个对象的严格比较返回 false,因为它在规范中如此指定。其逻辑类似于“西方”国家“双胞胎”的法律身份,虽然父母相同,但登记的姓名不同,各自享有独立个体的权利和义务。条件。。
两个对象的抽象比较结果是“令人困惑的”,因为它取决于对象的类型。
我假设我们正在讨论比较两个对象存储的值。在这种情况下,@M.Gress 提到的内容只有在两个对象都相同时才有效,即使它们的属性顺序也是如此,这不是很有用。理想的方法是比较所有属性,甚至是不可枚举的属性,但这是不可能的,至少不是在所有浏览器中。
在 JavaScript 最黑暗的部分,邪恶和混乱占主导地位,有两组比较运算符:
严格组包括运算符
===
和!==
,而非严格组包括——正如教师 Douglas Cockford 在他的书“JavaScript:好的部分”中所说——他们的邪恶双胞胎==
和!=
. 最后一组应该不惜一切代价避免,因为它们是许多头痛的原因。非严格组
应该尽量避免这组相等运算符,事实上,我建议你忘记它们的存在。理解使用运算符时问题根源的关键点如下:JavaScript 中的相等比较不是传递性的。这是什么意思?让我们在下面的代码中看到它:
为什么它们之间的比较
foo
和foo3
结果false
是相等的值?嗯,答案有点棘手。要了解为什么会发生这种情况,我们需要了解比较是如何在内部进行的。
这是什么意思?意思如下。如果比较两个不是对象的变量,如果它们内部不同,则使用 将它们转换为数字
ToNumber
,然后执行严格比较。这就是为什么这是真的:这也适用于布尔值,因为十进制表示中的布尔值将是 0 或 1。但是,当您将变量 X 与一个或两个对象进行比较时,会发生不同的情况:这里操作数 A 或 B(无论是对象)是用 计算的
ToPrimitive
,this内部方法只是简单地递归调用toString
并valueOf
获取一些原始值。随后,它利用ToNumber
来执行比较。如果比较两个对象,基本上非严格相等运算符将在它们比较内存中的相同引用时返回 true:
严格组
这里没有走弯路,先验证是同一个数据类型,再比较值。
如何比较两个对象?
如果我们谈论文字对象并比较它们自己的属性,那么迭代两个对象的属性就足够了。例如: