admin管理员组文章数量:1287810
currently I am following a book and am severely confused and have tried understandng the following code several times. My first confusion is actually approaching the problem of paring two objects a, and b.
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || typeof a != "object" ||
b == null || typeof b != "object")
return false;
var propsInA = 0, propsInB = 0;
for (var prop in a)
propsInA += 1;
for (var prop in b) {
propsInB += 1;
if (!(prop in a) || !deepEqual(a[prop], b[prop]))
return false;
}
return propsInA == propsInB;
}
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
currently I am following a book and am severely confused and have tried understandng the following code several times. My first confusion is actually approaching the problem of paring two objects a, and b.
function deepEqual(a, b) {
if (a === b) return true;
if (a == null || typeof a != "object" ||
b == null || typeof b != "object")
return false;
var propsInA = 0, propsInB = 0;
for (var prop in a)
propsInA += 1;
for (var prop in b) {
propsInB += 1;
if (!(prop in a) || !deepEqual(a[prop], b[prop]))
return false;
}
return propsInA == propsInB;
}
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
Share
Improve this question
edited Aug 24, 2016 at 15:26
Motombo
asked Jun 20, 2016 at 19:25
MotomboMotombo
1,7873 gold badges18 silver badges27 bronze badges
3
-
typeof is used here to make sure you're paring apples to apples. propsInX is used to count the number of props without paring values; if the count is different, so to are the objects, whereas if you just pared
{a:1,b:2}
to{a:1}
by looking at only the 2nd object, you'de get a false-positive. the alternative is to iterate both objects and pare; the counter removes the need for "double" iteration. – dandavis Commented Jun 20, 2016 at 19:28 - If they aren't objects, and they aren't equal, then that evaluates to false (objects parison is done based on reference value instead of object value - which is where the entire need to do this type of checking es into play in the first place). Beyond that it just recurses through the properties if it is an object and there is a nested object. – Travis J Commented Jun 20, 2016 at 19:29
-
!=
means "not equal".typeof a != "object"
means a is not of type "object" – Juan Tomas Commented Jun 20, 2016 at 19:29
4 Answers
Reset to default 3function deepEqual(a, b) {
if (a === b) return true;
First, we're checking if a
and b
are strictly equal (meaning, "referring to exactly the same thing"). Most things, such as strings and numbers, will pass this test if they are equal; objects are the exception, since two "identical" objects may not necessarily be the same object (they can just look the same).
if (a == null || typeof a != "object" ||
b == null || typeof b != "object")
return false;
Then we're saying that if either of the two is not an object, and they did not pass the last test, then they cannot be the same. Again, objects are the exception here, so the remaining code will take care of the case where a
and b
are both objects.
var propsInA = 0, propsInB = 0;
for (var prop in a)
propsInA += 1;
This code simply counts the number of properties of a
.
for (var prop in b) {
propsInB += 1;
if (!(prop in a) || !deepEqual(a[prop], b[prop]))
return false;
}
This code takes every property in b
, and checks that a
contains the same property with the same value. If a
doesn't have a property that b
has, or they are different, then the two objects cannot be equal.
return propsInA == propsInB;
}
Finally, if a
and b
do not have the same number of properties, then they cannot be equal. However, if they do have the same number of properties, then a
and b
must be equal, since a
has all the properties that b
has, and only those.
I'll walk you through it.
if (a === b) return true;
We check if these are the same thing, we'll e back to here later.
if (a == null || typeof a != "object" ||
b == null || typeof b != "object")
return false;
We check if one or neither of these things are objects are defined. We'll e back here too.
Keep these first two snippets in mind, they don't e into play until we call the function recursively.
var propsInA = 0, propsInB = 0;
These will be used to keep track of the number of properties in object A and B
for (var prop in a)
propsInA += 1;
for (var prop in b) {
propsInB += 1;
if (!(prop in a) || !deepEqual(a[prop], b[prop]))
return false;
}
return propsInA == propsInB;
}
We have two for loops. The first one just loops through all properties in A (look up For...in syntax if you're unfamiliar), and for each it increments the variable propsInA.
The second loop does the same for B, but here it gets more plicated. First it checks if that property exists in A, or if deepequal returns true. This is where the first two snippets we examined e into play. The first snippet is used here to return true if the properties we give it are the same. The second snippet says "if we passed properties instead of functions, stop here". This is important because this function only needs to go on past here if its the initial invocation. All recursive invocations only need to use the first part. If either of these two return false, we return false to the initial invocation, because we know there was a difference between A and B.
return propsInA == propsInB;
We can't return true here, because we don't actually know if there is just less properties in B. Even though everything else appeared the same, we can't assume that they have the same amount of properties. This assures, as a final check, that we will only return true if the number of properties in A is equal to the number in B
Feel free to ask me to explain further.
On this function
- First of, the function checks simply if the first parameter equals to the second one and then return
true
. typeof a! = "object"
- That check if the type of the parameters (a and b) are objects, if one of them is not an object, the function will end by returningfalse
.- Then if it passed this condition (a and b are objects) it will continue to the next step- a loop that will go through the items on the objects (a and b), and will count them
propsInA
for a andpropsInB
for b accordingly. - The next step will be to check if there is no items on the parameter, if so it will return false
- Otherwise the function will pare between
propsInA
andpropsInB
,if they are identical the function will end by returningtrue
otherwise it will returnfalse
.
Your algorithm behaves like this:
If
a
andb
are considered strictly equal, returntrue
a
andb
are considered strictly equal if one of these applies:- They are the same primitive value, except
NaN
- They are
+0
and-0
(or viceversa) - They are the same object (same reference).
This is done using the strict equality parison (
===
) operator.- They are the same primitive value, except
If either
a
orb
or both are not considered objects, returnfalse
o
is not considered object if one of these applies:o
is a primitive valueo
belongs to the Object type but has an internal [[Call]] method. That is, is a callable object, e.g. a function or a HTML<object>
element.o
is a non-callable non-standard exotic object whose implementation-defined returned by thetypeof
operator is different than"object
"`.
This is done using the
typeof
operator, which returns a string with the type of the value, except fornull
and maybe objects. Sincetypeof null === "object"
,a == null
is checked.If
a
andb
have the a different number of enumerable properties (taking into account both own and inherited ones), returnfalse
.This is counted by
propsInA
andpropsInB
.If
b
has an enumerable (own or inherited) property buta
doesn't have a (non-enumerable or enumerable, own or inherited, not necessarily the same asb
) property with the same name, returnfalse
.This is done iterating
for (var prop in b)
and checkingprop in a
.If
b
has an enumerable (own or inherited) property whose value is considered different by thedeepEqual
algorithm than the value of the same property ina
, returnfalse
.This is done iterating
for (var prop in b)
and checkingdeepEqual(a[prop], b[prop])
.Otherwise, return
true
.
I don't think it's a good algorithm. For example, it considers {}
, Object.prototype
and Object.create(null)
to be all equal, but I wouldn't say so.
本文标签: javascriptComparing two objects to see if equalStack Overflow
版权声明:本文标题:javascript - Comparing two objects to see if equal - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741327115a2372550.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论