I faced I bug I don’t totally understand so I would like to know why it happens. I understand it has something to do with the {…} spread operator but unclear what is the root of the problem.
Here is a simplified class of the one I used:
class Item {
id:number;
constructor(id:number) {
this.id = id;
}
compareTo = (i2:Item) => {
return this.id === i2.id;
}
}
Now this "Item" class was inside another custom class so I copied it with spread operator but when I started to use the object I faced a weird bug when comparing the item to itself:
const selectedObj = { item: new Item(1) };
let item:Item = {...selectedObj.item};
console.log(item.id) // 1
console.log(item.compareTo(item)) //true
item.id = 123;
console.log(item.id) //123
console.log(item.compareTo(item)) //false
When I inspected this further I noticed that inside the compareTo method "this.id" did not change. Why does this happen?
2
Answers
You’ve initialized the
compareTo
field with an arrow function; as such, it does not have its ownthis
context. Insteadthis
refers to whatever it refers to outside the arrow function body; for a field initializer it’s the class instance under construction. Which means thatcompareTo
is always going to bound to the specific class instance it was constructed with, and not the object on which it was called.If you modify
compareTo
to log whetherthis === i2
:you’ll see this behavior:
which demonstrates that
item.compareTo
is not bound toitem
, but is always bound toselectedObj.item
.Playground link to code
You need to use a class, like this.