-
Notifications
You must be signed in to change notification settings - Fork 15
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Consider undefined properties equivalent to missing properties. #21
Merged
benjamn
merged 1 commit into
main
from
consider-undefined-and-missing-properties-equivalent
Oct 1, 2020
Merged
Consider undefined properties equivalent to missing properties. #21
benjamn
merged 1 commit into
main
from
consider-undefined-and-missing-properties-equivalent
Oct 1, 2020
Conversation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Previously, an object `a` with a key `k` whose value is undefined (that is, `a[k] === void 0`) would not be considered deeply equal to another object `b` that is missing that key, but is otherwise deeply equal to the first object, even though `a[k] === b[k]`. This commit makes these two different kinds of undefined-ness equivalent, by efficiently ignoring undefined-valued keys when comparing objects. This allows more objects than before to be considered equivalent, but the equal(a, b) function still obeys the rules of equivalence relations: reflexivity, symmetry, and transitivity. This change is similar in spirit to the way we relaxed the strict === requirement for function objects in #12: more functions can be considered equivalent now, but the newly equivalent functions still obey the rules of equality, and thus the change is logically valid, a decision we are free to make but not forced to make. The additional leniency will be useful in situations where (for example) multiple options objects are combined by application code and then passed to an API, perhaps using ...spread syntax or Object.assign, and the API needs to decide if the new options are the same as previous options. This change allows the application code to avoid worrying about the difference between undefined and missing object properties, a discipline that can unnecessarily complicate the way the options need to be combined.
hwillson
approved these changes
Oct 1, 2020
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great - LGTM!
benjamn
added a commit
that referenced
this pull request
Sep 15, 2021
Since array equality checking no longer falls through to the object case, we can preserve the `definedKeys` behavior for objects (introduced in #21) for arrays, by treating any array holes as undefined elements, using an ordinary `for` loop. Using `a.every` doesn't work because `Array` iteration methods like `Array.prototyp.every` skip over holes.
benjamn
added a commit
that referenced
this pull request
Jan 21, 2022
Since array equality checking no longer falls through to the object case, we can preserve the `definedKeys` behavior for objects (introduced in #21) for arrays, by treating any array holes as undefined elements, using an ordinary `for` loop. Using `a.every` doesn't work because `Array` iteration methods like `Array.prototyp.every` skip over holes.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Previously, an object
a
with a keyk
whose value is undefined (that is,a[k] === void 0
) would not be considered deeply equal to another objectb
that is missing that key, but is otherwise deeply equal to the first object, thougha[k] === b[k]
.This commit makes these two different kinds of undefined-ness equivalent, by efficiently ignoring undefined-valued keys when comparing objects. This allows more objects than before to be considered equivalent, but the
equal(a, b)
function still obeys the rules of equivalence relations: reflexivity, symmetry, and transitivity.This change is similar in spirit to the way we relaxed the strict
===
requirement for function objects in #12: more functions can be considered equivalent now, but the newly equivalent functions still obey the rules of equality, and thus the change is logically valid, a decision we are free to make but not forced to make.The additional leniency will be useful in situations where (for example) multiple
options
objects are combined by application code and then passed to an API, perhaps using...spread
syntax orObject.assign
, and the API needs to decide if the newoptions
are different from previousoptions
. This change allows the application code to avoid worrying about the difference between undefined and missing object properties, a discipline that can unnecessarily complicate the way the options need to be combined.Since the
@wry/equality
package has not yet reached 1.0.0, this change will be a minor version bump (0.3.0). Extrapolating from the success of #12, I do not anticipate this change will cause problems in practice, but we could (in principle, in the future) consider allowing theequal
function to take options that configure how it behaves. If you're reading this because this PR caused you unexpected problems, please let me know below!