JavaScript Property Behavior Matrix A new JavaScript reference document, created by AI in collaboration with a user, provides a comprehensive matrix of how property types—enumerable vs non-enumerable, string vs symbol, and own vs inherited—interact with operators, loops, spread, and Object static methods. The matrix clarifies behaviors such as property access, assignment, deletion, and copying, highlighting distinctions like masking inherited properties and the exclusion of non-enumerable and symbol keys in certain operations. A comprehensive reference for how JavaScript property types interact with language operators, loops, spread, and Object static methods. Document Note:Created by AI Gemini in collaboration with the user. Enum vs Non-Enum: Refers to property enumerability enumerable: true vs enumerable: false , not TypeScript enum types. String vs Symbol: Refers to the property key type String keys like "a" vs Symbol keys like Symbol "a" . Own vs Inherited: Properties defined directly on the object instance vs properties inherited through the prototype chain. — Property value is evaluated. If it's an accessor, its ✓ Accessed Getter is executed.— Existing own property value is updated invokes an own ✓ Overwritten Setter if defined .— Assignment creates a new ⬖ Masked own data property on obj , masking the prototype or invokes an inherited Setter if defined . ✓ Deleted — Own property is removed from the object. 1 https://gist.github.com/starred.atom user-content-fn-1-bacf6fede3ac5ab18924c7e40bf71080 — Key exists and is detected ✓ Found true returned by existence check .— Property is included in the output array or loop iteration. For ✓ Included Object.values and Object.entries , reading the value invokes Getters if present.— Value is evaluated executing ✓ Copied Getters if present and assigned as a data property.— Raw descriptor object ✓ Described { get, set, value, ... } is read directly without invoking accessors.— Property is skipped/bypassed or returns ✗ Ignored false on existence checks, same as for missing properties . | Situation / Operation | Own String Enum | Own String Non-Enum | Own Symbol Enum | Own Symbol Non-Enum | Inherited String Enum | Inherited Non-Enum or Symbol | |---|---|---|---|---|---|---| val = obj.prop / val = obj prop | ✓ Accessed | ✓ Accessed | ✓ Accessed | ✓ Accessed | ✓ Accessed | ✓ Accessed | obj.prop = val / obj prop = val | ✓ Overwritten | ✓ Overwritten | ✓ Overwritten | ✓ Overwritten | ⬖ Masked | ⬖ Masked | delete obj.prop / delete obj prop | ✓ Deleted | ✓ Deleted | ✓ Deleted | ✓ Deleted | ✗ Ignored | ✗ Ignored | prop in obj | ✓ Found | ✓ Found | ✓ Found | ✓ Found | ✓ Found | ✓ Found | Object.hasOwn obj, prop / obj.hasOwnProperty prop | ✓ Found | ✓ Found | ✓ Found | ✓ Found | ✗ Ignored | ✗ Ignored | for prop in obj | ✓ Included | ✗ Ignored | ✗ Ignored | ✗ Ignored | ✓ Included | ✗ Ignored | Object.keys / Object.values / Object.entries | ✓ Included | ✗ Ignored | ✗ Ignored | ✗ Ignored | ✗ Ignored | ✗ Ignored | { ...obj } | ✓ Copied | ✗ Ignored | ✓ Copied | ✗ Ignored | ✗ Ignored | ✗ Ignored | Object.assign target, src | ✓ Copied | ✗ Ignored | ✓ Copied | ✗ Ignored | ✗ Ignored | ✗ Ignored | structuredClone obj | ✓ Copied | ✗ Ignored | ✗ Ignored | ✗ Ignored | ✗ Ignored | ✗ Ignored | JSON.stringify obj | ✓ Copied | ✗ Ignored | ✗ Ignored | ✗ Ignored | ✗ Ignored | ✗ Ignored | Object.getOwnPropertyNames obj | ✓ Included | ✓ Included | ✗ Ignored | ✗ Ignored | ✗ Ignored | ✗ Ignored | Object.getOwnPropertySymbols obj | ✗ Ignored | ✗ Ignored | ✓ Included | ✓ Included | ✗ Ignored | ✗ Ignored | Reflect.ownKeys obj | ✓ Included | ✓ Included | ✓ Included | ✓ Included | ✗ Ignored | ✗ Ignored | Object.getOwnPropertyDescriptor / Object.getOwnPropertyDescriptors | ✓ Described | ✓ Described | ✓ Described | ✓ Described | ✗ Ignored | ✗ Ignored | Footnotes - delete Operator Return Values & Mechanics: delete only affects own properties , leaving inherited prototype properties untouched and returning true . It returns true if an own property was successfully deleted, or if the property never existed in the first place. It returns false in non-strict mode or throws a TypeError in strict mode when attempting to delete an own non-configurable property . ↩ https://gist.github.com/starred.atom user-content-fnref-1-bacf6fede3ac5ab18924c7e40bf71080 - While both copy values invoking Getters on Object.assign vs. Object Spread { ...obj } : src , Object.assign target, src assigns values to target via target k = val . Thus, it triggers Setters if target or its prototype chain already defines a matching setter. Spread { ...src } always defines new own data properties on the object literal being constructed, completely bypassing any existing target setters. ↩ https://gist.github.com/starred.atom user-content-fnref-2-bacf6fede3ac5ab18924c7e40bf71080 ↩ https://gist.github.com/starred.atom user-content-fnref-2-2-bacf6fede3ac5ab18924c7e40bf71080 2 - Executes Getters on own enumerable string properties and recursively deep-clones values. structuredClone obj Constraints: Throws a if any property value is a DataCloneError Function or Method . Symbols, non-enumerable properties, and prototype chains are completely stripped. ↩ https://gist.github.com/starred.atom user-content-fnref-3-bacf6fede3ac5ab18924c7e40bf71080 - Executes Getters on own enumerable string properties. Automatically JSON.stringify obj Constraints: omits properties whose value evaluates to a Function , Symbol , or undefined when inside objects , or converts them to null when inside arrays . ↩ https://gist.github.com/starred.atom user-content-fnref-4-bacf6fede3ac5ab18924c7e40bf71080