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
Add a ment  | 

4 Answers 4

Reset to default 3
function 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 returning false.
  • 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 and propsInB 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 and propsInB,if they are identical the function will end by returning true otherwise it will return false.

Your algorithm behaves like this:

  1. If a and b are considered strictly equal, return true

    a and b 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.

  2. If either a or b or both are not considered objects, return false

    o is not considered object if one of these applies:

    • o is a primitive value
    • o 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 the typeof operator is different than "object"`.

    This is done using the typeof operator, which returns a string with the type of the value, except for null and maybe objects. Since typeof null === "object", a == null is checked.

  3. If a and b have the a different number of enumerable properties (taking into account both own and inherited ones), return false.

    This is counted by propsInA and propsInB.

  4. If b has an enumerable (own or inherited) property but a doesn't have a (non-enumerable or enumerable, own or inherited, not necessarily the same as b) property with the same name, return false.

    This is done iterating for (var prop in b) and checking prop in a.

  5. If b has an enumerable (own or inherited) property whose value is considered different by the deepEqual algorithm than the value of the same property in a, return false.

    This is done iterating for (var prop in b) and checking deepEqual(a[prop], b[prop]).

  6. 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