What are the benefits of making properties non-enumerable?

后端 未结 4 742
天涯浪人
天涯浪人 2020-12-04 16:34

Enumerability is one of the three attributes of a property: writability, enumerability, and configurability. My questions are:

  • What are the benefit of making p
4条回答
  •  谎友^
    谎友^ (楼主)
    2020-12-04 17:01

    There are no real practical uses for non-enumerable properties

    This is a very nice question that I was about to ask myself. After a bit of investigation, my conclusion is: you most certainly don't need this feature.

    Background

    For those who don't know what a non-enumerable property is, take a look at the links below:

    • What does enumerable mean?
    • Enumerability and ownership of properties

    You can actually enumerate them

    This is weird, but enumerating said "non-enumerable" properties is actually very simple:

    // start with some enumerable properties
    const foo = {
      a: 1,
      b: "yes",
      c: function () {}
    }
    
    // then add a couple of non-enumerable ones
    Object.defineProperty(foo, "d", { value: "hiding here", isEnumerable: false });
    Object.defineProperty(foo, "e", { value: 42, isEnumerable: false });
    
    const enumerableProperties = Object.keys(foo).join(", ");
    console.info("Enumerables: " + enumerableProperties);
    // Enumerables: a, b, c
    
    const ownPropertyNames = Object.getOwnPropertyNames(foo).join(", ");
    console.info("Enumerating also the non-enumerables: " + ownPropertyNames);
    // Enumerating also the non-enumerables: a, b, c, d, e

    When they say you can't enumerate them, they are referring specifically to Object.keys() and the for..in loop and the fact that they only return enumerable properties. That's not the case with getOwnPropertyNames().

    Don't use it

    Ok, now that we are on the same page: it looks to me like an obscure language feature, one that would only make my code more difficult to read and understand. I simply can't think of a truly legitimate use for it.

    Both existing answers talk about two very specific cases:

    1. it is useful when you are having to mess with a prototype of some third-party object to add some polyfill method without breaking existing code in the specific case that the code doesn't protect itself using hasOwnProperty() or Object.keys(). If that's your case, you're having to support very old code (i.e., legacy code that doesn't comply with today's best practices) and I feel sorry for you (although I know there are a lot of systems still being maintained today which fall into that case, unfortunately);

    2. it is useful for when you're developing a public library and want to keep your public-facing object clean. That is very specific, right? And I also would prefer not to pollute my library's code with several definePropertys just for that. Moreover, that answer is quickly getting old because we now have private fields. Finally, the answer also states that it would also keep the public namespace clean, but that's not true; the namespace is being polluted by the object itself, not its properties.

    So, unless you're in unfortunate position of having to maintain old code, forget about using this. You don't need it, trust me. If you find yourself in the situation that you need to hide some properties when enumerating an object, you are certainly modeling it wrong. Just put those properties in a separate object. They are not meant to live together with the other properties you have. This will keep you code cleaner and easier to understand, which is the single most important thing you should strive to achieve when writing code.

    Here's a more detailed article corroborating the idea that non-enumerable properties play no significant role nowadays.

提交回复
热议问题