问题(来自雄辩的Javascript第2版,第4章,练习4):
编写一个函数deepEqual,它接受两个值,只有当它们是相同值或具有相同属性的对象时才返回true,与递归调用deepEqual相比,这些对象的值也是相等的。
测试用例:
var 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我的代码:
var deepEqual = function (x, y) {
if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
if (Object.keys(x).length != Object.keys(y).length)
return false;
for (var prop in x) {
if (y.hasOwnProperty(prop))
return deepEqual(x[prop], y[prop]);
/*This is most likely where my error is. The question states that all the values
should be checked via recursion; however, with the current setup, only the first
set of properties will be checked. It passes the test cases, but I would like
to solve the problem correctly!*/
}
}
else if (x !== y)
return false;
else
return true;
}我想我已经有了大致的想法;但是,正如我在评论中所说的,程序将不会检查对象中的第二个属性。我觉得自己有一个结构/逻辑问题,只是以错误的方式使用递归,因为我最初打算循环这些属性,使用递归来比较第一个属性的值,然后继续循环到下一个属性,然后再进行比较。不过,我不确定这是否可能?
我考虑了很多,尝试了几种不同的方法,但这是我到目前为止得出的最正确的答案。有什么建议可以指引我走向正确的方向吗?
发布于 2014-08-22 21:59:44
正如你所怀疑的,你正在返回第一次看到的属性的匹配。如果该属性不匹配,则应返回false,但请继续查找其他属性。
此外,如果在false上没有找到prop属性,则返回y (即计数匹配,但不符合实际属性)。
如果所有属性都匹配,则返回true
var deepEqual = function (x, y) {
if (x === y) {
return true;
}
else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
if (Object.keys(x).length != Object.keys(y).length)
return false;
for (var prop in x) {
if (y.hasOwnProperty(prop))
{
if (! deepEqual(x[prop], y[prop]))
return false;
}
else
return false;
}
return true;
}
else
return false;
}
var deepEqual = function (x, y) {
if (x === y) {
return true;
}
else if ((typeof x == "object" && x != null) && (typeof y == "object" && y != null)) {
if (Object.keys(x).length != Object.keys(y).length)
return false;
for (var prop in x) {
if (y.hasOwnProperty(prop))
{
if (! deepEqual(x[prop], y[prop]))
return false;
}
else
return false;
}
return true;
}
else
return false;
}
var obj = {here: {is: "an", other: "3"}, 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}));
// → false
console.log(deepEqual(obj, {here: {is: "an", other: "2"}, object: 2}));
// → false
console.log(deepEqual(obj, {here: {is: "an", other: "3"}, object: 2}));
// → true
发布于 2017-08-14 21:14:48
觉得这个版本更易读(更容易理解)。不过,这一逻辑与上面的答案非常相似。(ES6这次)
function deepEqual(obj1, obj2) {
if(obj1 === obj2) // it's just the same object. No need to compare.
return true;
if(isPrimitive(obj1) && isPrimitive(obj2)) // compare primitives
return obj1 === obj2;
if(Object.keys(obj1).length !== Object.keys(obj2).length)
return false;
// compare objects with same number of keys
for(let key in obj1)
{
if(!(key in obj2)) return false; //other object doesn't have this prop
if(!deepEqual(obj1[key], obj2[key])) return false;
}
return true;
}
//check if value is primitive
function isPrimitive(obj)
{
return (obj !== Object(obj));
}顺便说一句,有一个欺骗版本的深度相等,它的工作像一个魅力),然而,它大约是1.6倍的速度。
,正如zero298注意到的,这种方法对属性排序很敏感,不应该被认真对待
function cheatDeepEqual(obj1, obj2)
{
return JSON.stringify(obj1) === JSON.stringify(obj2);
}发布于 2014-08-22 21:59:21
您可以在for循环之外使用一个变量来跟踪比较:
var allPropertiesEqual = true;
for (var prop in x) {
if (y.hasOwnProperty(prop)) {
allPropertiesEqual = deepEqual(x[prop], y[prop]) && allPropertiesEqual;
} else {
allPropertiesEqual = false;
}
}
return allPropertiesEqual;前面的示例不是故意优化的。因为您正在比较对象,您知道只要找到一个不等式就可以return false,并且可以在前面检查的所有属性相等的情况下继续循环:
for (var prop in x) {
if (y.hasOwnProperty(prop)) {
if (! deepEqual(x[prop], y[prop]) )
return false; //first inequality found, return false
} else {
return false; //different properties, so inequality, so return false
}
}
return true;https://stackoverflow.com/questions/25456013
复制相似问题