The attribute used to control whether a property is non-enumerable is enumerable.
Object.defineProperty() accepts a property descriptor containing attributes such as value, writable, configurable, and enumerable. Setting enumerable: false hides the property from common enumeration operations, including Object.keys(), for...in loops, Object.assign(), and object spread. The property still exists and can normally be accessed directly by name.
A frequent mix-up is the default behavior: properties created with ordinary assignment are enumerable by default, but properties created with Object.defineProperty() default to enumerable: false when the field is omitted. Thus Object.defineProperty(obj, "secret", { value: 42 }) creates a non-enumerable property, while explicitly writing enumerable: true makes it visible to enumeration.
The other descriptor attributes have different jobs. value supplies the stored data, writable controls assignment, and configurable controls deletion and descriptor changes. They do not determine whether a property appears during enumeration.