JSONPath is a query language, not a property accessor
The difference that matters is that a query returns a set. `data.users[0].email` in JavaScript returns one value or throws. The JSONPath expression `$.users[*].email` returns every email in the array as a list, and returns an empty list rather than an error if there are none. That set-oriented behaviour is what makes it useful for extraction rather than navigation.
The syntax borrows deliberately from XPath. `$` is the root, `.` and `[...]` are child access, `*` is a wildcard, `..` is a recursive descent that searches every level, and `[?(...)]` is a filter expression. That vocabulary is small enough to learn in a sitting and expressive enough to cover most extraction tasks.
Recursive descent is the feature that earns its keep on unfamiliar data. `$..email` finds every `email` field anywhere in the document, at any depth, without you needing to know the structure. When you are exploring a response you did not design, that is often the fastest possible first query.