我正在学习JavaScript并尝试做这个练习:
编写一个函数
deepEqual
,该函数采用两个值,仅当它们是相同的值或具有相同属性的对象时才返回true
,其中值 的属性与递归调用相比相等deepEqual
.若要确定是否应直接比较值(使用
===
运算符 为此(,或者比较它们的属性,您可以使用typeof
运算符。 如果它为这两个值生成"对象",则应进行深入比较。 但是你必须考虑到一个愚蠢的例外:因为历史上 偶然,typeof null
也产生了"对象"。当您需要查看属性时,
Object.keys
函数将很有用 的对象进行比较。
这是我的解决方案,给了我true
,false
,false
这是错误的
function deepEqual (a,b) {
if (a===b) return true;
if (typeof a=="object" && typeof b=="object") {
let x=Object.keys(a), y=Object.keys(b);
if (x.lenght==y.lenght) {
for (key of x){
if (y.includes(key)){
if (a[key]===b[key]) return true;
else return false;
}
}
}
return true;
}
}
let obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
console.log(deepEqual(obj, {here: 1, object: 2}));
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
这是正确的解决方案:
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || typeof a != "object" ||
b == null || typeof b != "object") return false;
let keysA = Object.keys(a), keysB = Object.keys(b);
if (keysA.length != keysB.length) return false;
for (let key of keysA) {
if (!keysB.includes(key) || !deepEqual(a[key], b[key])) return false;
}
return true;
}
let obj = {here: {is: "an"}, object: 2};
console.log(deepEqual(obj, obj));
// → true
console.log(deepEqual(obj, {here: 1, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an"}, object: 2}));
// → true
我真的无法理解我写的东西有什么问题以及如何解决它。
非常感谢您帮助菜鸟:)
以下是代码中的问题:
1(对象测试:
if (typeof a=="object" && typeof b=="object") {
这很好,但如果这个条件不成立怎么办?您没有任何处理这种情况的代码,因此该函数将返回undefined
。它应该返回false
。
其次,JavaScript 中有一个奇怪的事情,这个问题已经警告过你——你应该考虑到它:
。因为历史的偶然,
typeof null
也产生了"对象"。
。因此,您需要对此进行单独的测试,因为null
并不是真正的对象,并且当您将其视为对象时,代码会产生错误。
在您的代码中,null
值将通过此if
测试,然后执行Object.keys(null)
,这会触发异常。不应允许在其中使用null
值。
2( 比较属性数量
if (x.lenght==y.lenght) {
有拼写错误。它不是lenght
,而是length
(2x(。 再说一次,如果这个条件不成立怎么办?除了该if
块之后的return true
之外,没有处理这种情况的代码,但您的函数应该返回false
。
3( 检查两个对象中是否存在属性
if (y.includes(key)){
此测试有效,但不是最佳测试。includes
比仅检查该key in b
要慢(遗憾的是参考解决方案也使用includes
(。
和以前一样,如果这个条件不成立怎么办?该函数应立即退出循环并返回false
,但这并没有发生...
4( 检查相同属性的值是否深度相等。
if (a[key]===b[key]) return true;
这种情况不会进行深入比较。这个问题已经告诉你在这里做什么:
。其中属性的值与递归调用相比相等
deepEqual
因此,在这种情况下,您应该执行递归调用,以便以相同的方式比较任何嵌套对象。当这两个值是单独的对象时,只会false
a[key]===b[key]
。但是,当这些对象具有相同的属性和相同的值时,条件确实应该true
......这正是您的函数能够做的:所以在这里调用它。
其次,现在不是return true
的时候,因为这将在不检查其他键的情况下退出循环,并且结果可能是负面的......而一个"负面"就足以使整体最终结果false
.因此,虽然情况良好,但您应该继续循环。
5( 当值不同时
else return false;
是的,这是return false
的正确时机.
6( 当所有测试成功时
return true;
这是唯一正确的return true
,但您应该解决我答案中的第二句话,以便在长度不同时不会执行此陈述。
正确的代码
由于您已经有正确的代码可以比较,因此在此处重复该代码有点矫枉过正。