-2

For example, the following two javascript object have properties include "name", "age" and "phoneNumber".

const personA = {
   name: Andy,
   age: "24",
   phoneNumber: "28173516374"
}
const personB = {
   name: "Amy",
   age: 25,
   phoneNumber: "+85 28173516374"
}

For the property "phoneNumber", I don't want others use it with operator "===" to compare with other string like personA.phoneNumber === personB.phoneNumber, because for the value of a phoneNumber, it should be the same either with or without a prepended country code. For other developers who don't have this knowledge background, they possibly use === to do the compare between two variable with value of a phone number and it will raise some bugs.

So I need a way to limit the usage of === on specific property. I have came up with several solutions, but they still have more or less disadvantage.

Solution 1: Transform the type of all properties which represents a phone number from string to an class PhoneNumber, this class will handle all the comparation and value formatting. However, I have to use new to create that object and should modify many places. Because this property is used everywhere in my project. After trying several times, I forgave applying this solution.

Solution2: Use a common function to compare two phone number. As I have said before, not all developers and reviewers know that function. Even if I address it in document, still have someone forget that.

Now I am trying to develop an eslint rules to limit the usage of === on specific property. Do you have other idea?

jiaqin lin
  • 21
  • 7
  • 7
    Probably not, this is really weird. How would such a property be accessible at all, then? – CertainPerformance May 12 '21 at 02:33
  • 4
    No, this is impossible. [What's up with comparison operators today?](https://stackoverflow.com/questions/67495190/preventing-object-comparision-in-javascript) – Bergi May 12 '21 at 02:37
  • Use `_name` instead of `name` to signify that you don't want other code to mess with that property. – Bergi May 12 '21 at 02:38
  • 1
    For example, an object has a property named `phoneNumber`. As we all know, the two phone number with or without the prepended country code is the same, so we cannot just compare it simply with`===`. We should call a function to do that comparation. However, I can't make sure that others have this background knowledge. – jiaqin lin May 12 '21 at 02:39
  • 2
    You might want to create a class for this and give it something like a checkPhoneNumberMatches method. – Aadmaa May 12 '21 at 02:42
  • I have considered that solution of creating a class to handle that, but it require huge effort for my project. – jiaqin lin May 12 '21 at 02:44
  • 1
    *Does* your project have such a function to compare phone numbers? – Bergi May 12 '21 at 02:47
  • 1
    Don't call the property just `phoneNumber`, but have a `rawPhoneNumber` property and a `normalisedPhoneNumber` (or `phoneNumberWithCountryCode`) getter. Use descriptive names, comments, and documentation to give others this background knowledge about the domain and how to use your code. – Bergi May 12 '21 at 02:52
  • Thanks @Bergi, It's a good idea to consider for me! – jiaqin lin May 12 '21 at 02:56
  • Try adding JSDoc and clarifying that the comparison should be through a function – First dev May 12 '21 at 03:54
  • @jiaqinlin Please [edit] your question and include these details there, not in the comments. Currently, your question is still an [XY problem](//meta.stackexchange.com/a/66378/289905). You cannot alter the `===` behavior, but you can make `phoneNumber` private, and expose just a `phoneNumberMatches` method. – Sebastian Simon May 12 '21 at 09:44
  • "*Because this property is used everywhere in my project, I would have to modify many places*" - I think this is your core problem that should be solved. Sure, it's a pain, but it'll be worth it, and simplify future refactorings. Also try introducing more abstractions so that you don't *directly* use the property every - e.g. by creating persons using a `Person` class or at least a factory function, not with object literals. But a class for phone numbers is the proper solution. – Bergi May 12 '21 at 16:18
  • Regarding an EsLint rule, you can try building something with https://eslint.org/docs/rules/no-restricted-syntax. – Bergi May 12 '21 at 16:19

1 Answers1

1

Sorry for my weak English.

If the task is to control who can read the field value and who cannot, then this can be solved in several ways.

  1. If you can change the structure of the Object, then getters and setters are suitable for you. MDN: Getter MDN: Setter

A simplified example solution would look like this:

{
    let admin;
    const personA = {

        age: "24",
        sex: "man",

        privateName: "Jhon",
        get name() {

            return (admin === true ? this.privateName : "***");
        },
        set name(v) {
            return (admin === true ? this.privateName = v : "***")

        }
    }
  admin = false;
    personA.name = "Mary"
    console.log(personA.name)
  
    admin = true;
    console.log(personA.name)
    personA.name = "Mary"
    console.log(personA.name)
}
Instead of outputting ***, we can return an exception.
  1. If you cannot change the structure, then the same can be done using a proxy. MDN: Proxy

  2. If you cannot use a proxy, then you can change the behavior of the object's properties using Object.defineProperty. That is, set the same getters and setters on an already existing object. MDN: Object.defineProperty

Demi Murych
  • 129
  • 3
  • Thanks for your answer. This cannot solve my pain point. I only want to control the usage of `===` for specific property – jiaqin lin May 12 '21 at 05:27