Comparing objects: Why am I getting different results using the same approach?

Tell us what’s happening:

(see the screenshots) I’m comparing two identical objects in 2 cases, but ones return true and another false. I though it was because in spite of the same properties and value pairs each pair is allocated in different memory spaces, but from my point of view that doesn’t explain why the other function is returning true.

Why am I getting different results using the same approach?

Your code so far


function whatIsInAName(collection, source) {
// What's in a name?
var arr = [];
// Only change code below this line

arr = collection.filter(objInArr => 
objInArr.hasOwnProperty(Object.keys(source)))

// Only change code above this line
return arr;
}

console.log(whatIsInAName([{ "apple": 1 }, { "apple": 1 }, { "apple": 1, "bat": 2 }], { "apple": 1 }))

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36 OPR/66.0.3515.72.

Challenge: Wherefore art thou

Link to the challenge:

Comparing two object in Javascript is a bit problematic.
A true deep comparison is not so easy to achieve, for a reference look at how lodash implements _isEqual() :slight_smile:

This is partially due to the fact that for each new object JS allocate a new memory “space”.
This means that for JS two “ponters” to an object are identical if they refer to the same memory address.

Example

let x = {
  "foo": "bar"
}

let y = {
  "foo": "bar"
} 

let z = {...x}; 

let j = x;

x === y  // false
x === z // false
x === j // true

Given this premise, your ways to compare two object is not sufficient for a true “deep” comparison.
Your function is looking if for each key in source, there’s a key in objInArray

objInArr.hasOwnProperty(Object.keys(source))

This has the flaw, like in your example that to output a positive outcome source needs to have the same keys, but it’s not true the other way around:

Consider this example:

let a = {
  "foo": "bar",
  "extra": "props",
  "cool": true,
}

let b = {
  "foo": "bar"
}
a.hasOwnProperty(Object.keys(b)) // true

This will produce true since a has all the keys of b; but not the other way around.

Hope this won’t confuse too much :+1:

To add to this, there’s a basic syntax error:

hasOwnProperty check whether an object has one specific property. Property keys are strings. So

const example = { foo: 1, quux: 2 };
example.hasOwnProperty("foo") // true
example.hasOwnProperty("bar") // false

The Object.keys function returns an array of the keys of an object.

example.hasOwnProperty(["foo", "quux"]);

example does not have the property keyed ["foo", "quux"] - it can’t, it’s an object and objects cannot have arrays as keys, only strings.

2 Likes

Thank you Dan!.
Wouldn’t be a solution to iterate on each possible key in source and extract each one to use it as an argument into hasOwnProperty (which should iterate on collection as much as number of keys source has)?

Yep, that would definitely work. You can use every to iterate over and return true if hasOwnProperty is true for every one.

Note that while that fulfils one of the conditions (keys are the same), it doesn’t fulfil the second (values as well). Look at Object.entries to get keys and values, you maybe won’t need hasOwnProperty when you use this (I’ll leave it to you to try out things though)

1 Like

Great! I’m gonna try and I’ll tell you.