{"id":4720,"date":"2018-07-28T10:11:48","date_gmt":"2018-07-28T10:11:48","guid":{"rendered":"https:\/\/tinjurewp.com\/jsblog\/?p=2026"},"modified":"2018-07-28T10:11:48","modified_gmt":"2018-07-28T10:11:48","slug":"deep-dive-into-javascript-property-descriptors","status":"publish","type":"post","link":"https:\/\/learncode.tinjurewp.com\/deep-dive-into-javascript-property-descriptors\/","title":{"rendered":"Deep Dive into JavaScript Property Descriptors"},"content":{"rendered":"<p class=\"note icon-note\"><strong>Note<\/strong>: This post is work-in-progress learning-note and still in active development and updated regularly.<\/p>\n<p>In a previous learning-post <a href=\"https:\/\/tinjurewp.com\/jsblog\/javascripts-objects-the-basics\/\" target=\"_blank\" rel=\"noopener\">JavaScript Objects &#8211; The Basics<\/a>, we discussed simple <code>key:value<\/code> object properties (values associated with properties). The <em>value<\/em> is one of the attribute of a property. Other attributes include <em>enumerable<\/em>, c<em>onfigurable<\/em> and <em>writable<\/em>. These attributes further define an object how its properties can be accessed.<\/p>\n<blockquote><p>Any property can have zero or more property attributes. <cite>Property Attributes, MDN<\/cite><\/p><\/blockquote>\n<p>In a previous learning-post <a href=\"https:\/\/tinjurewp.com\/jsblog\/javascripts-objects-the-basics\/\" target=\"_blank\" rel=\"noopener\">JavaScript Objects &#8211; The Basics<\/a>, use of <code>for..in<\/code> iteration in an object was\u00a0 discussed briefly. Enumerable properties show up in <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Statements\/for...in\" target=\"_blank\" rel=\"noopener\">for\u2026in<\/a> loops (once <code>for each<\/code> property) unless the property\u2019s name is\u00a0<a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Symbol\" target=\"_blank\" rel=\"noopener\">Symbol<\/a>. In this learning post, we will deep dive into object attributes and enumerability.<\/p>\n<h3>Object properties<\/h3>\n<p>Object properties contain a <code>key<\/code> and three or more <em>attributes<\/em>, (which hold property data).<\/p>\n<p>ECMAScript 6 (ES6) supports following attributes which <a href=\"http:\/\/rauschma.de\/\" target=\"_blank\" rel=\"noopener\">Dr Rauschmayer<\/a> groups them into the following three categories:<\/p>\n<div class=\"article-quote\">\n<ul>\n<li>All Properties:\n<ul>\n<li><code>enumerable<\/code>: Setting this attribute to <code>false<\/code> hides the property from some operations.<\/li>\n<li><code>configurable<\/code>: Setting this attribute to <code>false<\/code> prevents several changes to a property (attributes except <code>value<\/code> can\u2019t be change, property can\u2019t be deleted, etc.).<\/li>\n<\/ul>\n<\/li>\n<li>Normal properties (data properties &amp; methods):\n<ul>\n<li><code>value<\/code>: holds the value of the property.<\/li>\n<li><code>writable<\/code>: controls whether the property\u2019s value can be changed.<\/li>\n<\/ul>\n<\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Operators\/Property_Accessors\" target=\"_blank\" rel=\"noopener\">Accessors<\/a> (getters\/setters):\n<ul>\n<li><code>get<\/code>: holds the getter (a function).<\/li>\n<li><code>set<\/code>: holds the setter (a function).<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<\/div>\n<p>These property attributes are not visible when we normally create an object, because they remain hidden and set to <code>true<\/code> by default. The following table from <a href=\"https:\/\/abdulapopoola.com\/2016\/11\/21\/deep-dive-into-javascript-property-descriptors\/\" target=\"_blank\" rel=\"noopener\">this<\/a> post, summarizes how these property descriptor attribute fields are configured by default.<\/p>\n<table class=\"learnjs\">\n<thead>\n<tr class=\"learnjs\">\n<th>Attributes<\/th>\n<th>Data descriptor<\/th>\n<th>Accessor descriptor<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>value<\/td>\n<td>Yes<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td>writable<\/td>\n<td>Yes<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td>enumerable<\/td>\n<td>Yes<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>configurable<\/td>\n<td>Yes<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>get<\/td>\n<td>No<\/td>\n<td>Yes<\/td>\n<\/tr>\n<tr>\n<td>set<\/td>\n<td>No<\/td>\n<td>Yes<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Lets look at in the following example and retrieve these property attributes using <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/getOwnPropertyDescriptor\" target=\"_blank\" rel=\"noopener\">Object.getOwnPropertyDescriptor()<\/a> method.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/initialize myCar Object\nconst myCar = { year: 2017 }\n\n\/\/access myCar object property\nObject.getOwnPropertyDescriptor(myCar, &#039;year&#039;)\n\/\/OUTPUT\n{ value: 2017, \n  writable: true, \n  enumerable: true, \n  configurable: true\n}<\/code><\/pre>\n<p>In the example above, enumberable attribute is set to <code>true<\/code>. By default, every property is set to <code>true<\/code>.<\/p>\n<p>Now lets add a new property to <code>myCar<\/code> object using <strong>dot (<code>.<\/code>) notation<\/strong>.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/ add a model property\n myCar.make = &quot;Toyota&quot;;\n\n\/\/access property atrutes\nObject.getOwnPropertyDescriptor(myCar, &#039;make&#039;)\n\/\/OUTPUT\n{ value: &quot;Toyota&quot;, \n  writable: true, \n  enumerable: true, \n  configurable: true\n }<\/code><\/pre>\n<p>As shown in the example, enumerable and other attributes are set to <code>true<\/code> by default.<\/p>\n<h5>Defining Property Descriptors<\/h5>\n<p>The property attributes can be specified and defined using <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/defineProperty\" target=\"_blank\" rel=\"noopener\"><code>Object.defineProperty()<\/code><\/a> method. A basic syntax shown below:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/basic syntax\nObject.defineProperty(obj, propertyName, descriptor)<\/code><\/pre>\n<p><strong>Parameters<\/strong><\/p>\n<ul>\n<li><code>obj<\/code> : The object on which to define property<\/li>\n<li><code>propertyName<\/code> : The name of the property to be defined or modified.<\/li>\n<li><code>descriptor<\/code> : The descriptor of the property being defined or modified.<\/li>\n<li><em>Return value<\/em>: The object that was passed to the function.<\/li>\n<\/ul>\n<p>In the example below lets create and define an simple object:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/ create and &amp; define an empty object\nconst myCar = {};\n\/\/create object with defineProperty method\nObject.defineProperty(myCar, &#039;make&#039;, {\n  value: &quot;Toyota&quot;,\n});\n\/\/OUTPUT\n{make: &quot;Toyota&quot;}\n\n\/\/Access default attributes\nObject.getOwnPropertyDescriptor(myCar, &#039;make&#039;);\n\/\/OUTPUT\nobject {\n value: &quot;Toyota&quot;,\n writable: false,\n enumerable: false,\n configurable: false\n}<\/code><\/pre>\n<p>When we compare normally created &amp; defined <code>myCar<\/code> object earlier, with the <code>myCar<\/code> object value using <code>Object.defineProperty()<\/code> method (above, lines: 4-6), all the property attributes of the &#8216;<code>make<\/code>&#8216; are set to <code>false<\/code> (line ).<\/p>\n<p>That means the <code>make<\/code> attributes are immutable, not configurable, and not enumerable as shown below:<\/p>\n<pre class=\"line-numbers\" data-start=\"19\"><code class=\"language-javascript\">\/\/re-assign a new value\nmyCar.make = &quot;Honda&quot;; \/\/=&gt;logs &quot;Honda&quot;\n\n\/\/access myCar.make \nconsole.log(myCar.make);\n\/\/OUTPUT\n&quot;Toyota&quot; \/\/ writable = false\n\/\/delete myCar.make\ndelete myCar.make; \n\/\/OUTPUT\nfalse \/\/configurable=false\n\/\/non-enumerable\nObject.keys(myCar); \n\/\/OUTPUT\n[] \/\/enumerable = false<\/code><\/pre>\n<h5>How to Validate Property Existence<\/h5>\n<p>To better understand how object property descriptors are defined, lets revisit our <code>myCar<\/code> object below:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/ create and &amp; define an empty object\nlet myCar = { year: undefined };\n\/\/add make proprty with defineProperty method\nObject.defineProperty(myCar, &#039;make&#039;, { });\n\n\/\/access Property values\nconsole.log(myCar.year); \/\/OUTPUT =&gt; undefined\nconsole.log(myCar.make); \/\/OUTPUT =&gt; undefined\n\n\/\/access not-existing property value\nconsole.log(myCar.model); \/\/OUTPUT =&gt; undefined<\/code><\/pre>\n<p>In the example above, <code>myCar<\/code> object was created normal way and <code>year<\/code> property was assigned with &#8220;<code>undefined<\/code>&#8221; value (line 2). Next, a <code>make<\/code> property was added to <code>myCar<\/code> object with <code>Object.defineProperty()<\/code> method without any value (<em>empty<\/em>). When property values of <code>year<\/code> and <code>make<\/code> in <code>myCar<\/code> object were accessed, both property log <code>undefined<\/code> output, even for make property with empty value field. Even non-exiting property <code>model<\/code> outputs a undefined value (line 11).<\/p>\n<p>Because every object descended from <code>myCar<\/code> inherits <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/hasOwnProperty\" target=\"_blank\" rel=\"noopener\"><code>hasOwnProperty()<\/code><\/a> method. Using this method an object property can be determined whether an object has a direct property of that object.<\/p>\n<pre class=\"line-numbers\" data-start=\"12\"><code class=\"language-javascript\">\/\/verify with Object.hasOwnProperty()\nmyCar.hasOwnProperty(&#039;year&#039;); \/\/OUTPUT =&gt; true\nmyCar.hasOwnProperty(&#039;make&#039;); \/\/OUTPUT =&gt; true\nmyCar.hasOwnProperty(&#039;model&#039;); \/\/OUTPUT =&gt; false<\/code><\/pre>\n<p>In the example above, two existing properties (<code>year<\/code> &amp; <code>make<\/code>) of <code>myCar<\/code> object return <code>true<\/code> (lines: 13-14), where as non-existing property returns <code>false<\/code> (line: 15).<\/p>\n<h5>Modify Exiting Properties with <code>defineProperty<\/code><\/h5>\n<p>The <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/defineProperty\" target=\"_blank\" rel=\"noopener\"><code>Object.defineProperty()<\/code><\/a> method allows to create objects and modify or customize properties and their values as shown in the example below:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/ Create myCar object\nlet myCar = {}; \/\/empty object\n\/\/add property\nObject.defineProperty(myCar, &#039;make&#039;, {\n  value: &#039;Toyota&#039;,\n  writable: true\n});\n\n\/\/modify writable descriptor\nObject.defineProperty(myCar, &#039;make&#039;, {\n  value: &#039;Toyota&#039;,\n  writable: false\n});\n\n\/\/access property Descriptor\nObject.getOwnPropertyDescriptor(myCar, &#039;make&#039;);\n\/\/OUTPUT\nObject {\n  value: &#039;Toyota&#039;, \/\/unchanged\n  writable: false, \/\/ modified\n  enumerable: false,\n  configurable: false\n}<\/code><\/pre>\n<p>In the example above, an empty <code>myCar<\/code> object was created (line 2). A <code>make<\/code> property was added to <code>myCar<\/code> object using <code>Object.defineProperty()<\/code> method and defined its two attributes <code>value: &#039;Toyota&#039;<\/code> and <code>writable: true<\/code> (lines: 4-7).\u00a0 Now when we access descriptor attributes of <code>make<\/code> property using <code>Object.getOwnDescriptor()<\/code> method (line 10). The output result shows (lines: 11-16) <code>value<\/code> and <code>writable<\/code> as defined before (line: 12-13) but other two attributes <code>enumerable<\/code> and <code>configurable<\/code> were not defined were set to <code>false<\/code> by default (lines: 14-15).<\/p>\n<p>Using <code>Object.defineProperty()<\/code> the descriptor attributes of <code>make<\/code> property can be modified. In the example above, the <code>writable<\/code> attribute was changed from <code>true<\/code> to <code>fals<\/code>e (line: 21) and the modification is confirmed in its output (line: 21).<\/p>\n<h5>Writable Descriptor Attribute<\/h5>\n<p>The <code>writable<\/code> attribute\u00a0 is set to <code>false<\/code> by default when property is defined with <code>Object.definePropert()<\/code> method and thus the property is <em>non-writable<\/em> and can&#8217;t be reassigned.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/ Create myCar object\nlet myCar = {}; \/\/empty object\n\/\/add property\nObject.defineProperty(myCar, &#039;make&#039;, {\n  value: &#039;Toyota&#039;,\n  writable: true \/\/defaults false\n});\n\/\/access property value\nconsole.log(myCar.make); \/\/=&gt; Toyota\n\n\/\/Change property value\nmyCar.make = &quot;Honda&quot;; \/\/=&gt; Honda<\/code><\/pre>\n<p>In the example above, revisiting <code>myCar<\/code> object its <code>make<\/code> property is\u00a0 assigned <code>&#039;Toyota&#039;<\/code> value and its <code>writable<\/code> attribute is defined as <code>true<\/code> (line 6), default is <code>false<\/code>. Value of make can be reassigned to <code>&#039;Honda&#039;<\/code> (line 12).<\/p>\n<pre class=\"line-numbers\" data-start=\"13\"><code class=\"language-javascript\">\/\/set writable attribute to false\nObject.defineProperty(myCar, &#039;make&#039;, {\n    writable: false\n});\n\/\/access property value\nconsole.log(myCar.make); \/\/=&gt; Honda\n\n\/\/change property value\nmyCar.make = &quot;Toyota&quot;; \/\/ logs &quot;Toyota&quot; (TypeError in &#039;strict mode&#039;\n\/\/access property value\nconsole.log(myCar.make); \/\/OUT =&gt; Honda\n\n\/\/try modifying writable to true\nObject.defineProperty(myCar, &#039;make&#039;, {\n    writable: true\n});\n\/\/OUTPUT\nUncaught TypeError: Cannot redefine property: make<\/code><\/pre>\n<p>In the example above, the <code>writable<\/code> attribute of <code>make<\/code> property is defined as <code>false<\/code> (line 15). Value of <code>make<\/code> property can&#8217;t be modified (line 21) and throws <code>TypeError<\/code>.<\/p>\n<p>Once the <code>writable<\/code> attribute is set to <code>false<\/code>, it can&#8217;t be changed back to <code>true<\/code> (lines: 26-28) again (the change is permanent &#8211; ONE way only) and throws <code>cannot refine property TypeError<\/code> (line 30).<\/p>\n<p class=\"tip icon-note\"><strong>Tip<\/strong>: any modification in the <code>writable<\/code> attribute is permanent and ONE way only. Once its set <code>false<\/code> can&#8217;t be changed back to <code>true<\/code>.<\/p>\n<h5>Configurable Descriptor Attribute<\/h5>\n<p>As demonstrated in the previous section, when <code>writable<\/code> attribute is set to <code>false<\/code>, it prevents from changing property value only. However the property can still be modified.<\/p>\n<p>In the example below, lets revisit &amp; continue from our <code>myCar.make<\/code> property attribute setting from previous section, add <code>configurable<\/code> descriptor and set it to <code>true<\/code> (line 7). The <code>myCar.make<\/code> property value can still be modified by deleting the <code>myCar.make<\/code> property (line 13) and reassigning a new value <code>&#039;Toyota&#039;<\/code> (line 15).<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/ Create myCar object\nlet myCar = {}; \/\/empty object\n\/\/add property\nObject.defineProperty(myCar, &#039;make&#039;, {\n  value: &#039;Honda&#039;,\n  writable: false,\n  configurable: true\n})\n\/\/access property value\nconsole.log(myCar.make); \/\/ =&gt; Honda\n\n\/\/delete property &amp; reassign value\ndelete myCar.make; \/\/=&gt; true\n\/\/modify &amp; reassign property value\nmyCar.make = &#039;Toyota&#039;; \/\/ logs &#039;Toyota&#039;\n\n\/\/access modified property value\nconsole.log(myCar.make);  \/\/OUTPUT =&gt; Toyota<\/code><\/pre>\n<p>For example, if we don&#8217;t like property values to be <em>constant<\/em>, and not modifiable then this can be achieved by setting <code>enumerable<\/code> attribute to <code>true.<\/code> In the example below, lets examine this property revisiting <code>myCar<\/code> object and a new <code>model: &#039;Camry&#039;<\/code> property value.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/ Create myCar object\nlet myCar = {}; \/\/empty object\n\/\/add a model property\nObject.defineProperty(myCar, &#039;model&#039;, {\n  value: &#039;Camry&#039;,\n  writable: true,\n  configurable: false\n})\n\/\/check descriptor attribute setting\nObject.getOwnPropertyDescriptor(myCar, &#039;model&#039;);\n\/\/OUTPUT\n object {\n  value: &#039;Camry&#039;,\n  writable: true,\n  configurable: false,\n  enumerable: false \/\/default setting\n})\n\/\/modify enumerable setting\n&quot;use strict&quot;;\nObject.defineProperty(myCar, &#039;model&#039;, {\n    enumerable: true\n});\n\/\/OUTPUT\nUncaught TypeError: Cannot redefine property: model\n\n\/\/delete model property\ndelete myCar.model; \/\/=&gt; false (non-configurable)\n\/\/access property value\nconsole.log(myCar.model);\/\/=&gt; Camry\n\/\/modify writable setting to false\n&quot;use strict&quot;;\nObject.defineProperty(myCar, &#039;model&#039;, {\n    writable: false\n});\/\/=&gt; logs &quot;Camry&quot;\n\/\/modify property value\nmyCar.model = &#039;Corolla&#039;; \/\/=&gt; logs &quot;Corolla&quot;\n\/\/access model property value\nconsole.log(myCar.model);\/\/=&gt; Camry (not modified)<\/code><\/pre>\n<p>In the example above, a <code>model<\/code> property of <code>myCar<\/code> object is defined using <code>Object.propertyDefine()<\/code> method (lines: 4-8) its descriptor attributes are set as <code>value<\/code> to <code>Camry<\/code>, <code>writable<\/code> to <code>true<\/code> and <code>configurable<\/code> to <code>false<\/code>.<\/p>\n<p>By default, its <code>enumerable<\/code> attribute is set to <code>false<\/code> (line 16). If we modify the <code>enumerable<\/code> attribute to <code>true<\/code> (lines: 18-22), under &#8216;<em>strict mode<\/em>&#8216; its throws out<br \/>\n<code>TypeError: Cannot redefine property<\/code> (line 24).<\/p>\n<p class=\"note icon-note\"><strong>Note<\/strong>: Errors are thrown out only in\u00a0 &#8220;<em>strict use<\/em>&#8221; mode. Modification of attribute properties may be ignored in non-strict.<\/p>\n<p>Once the <code>configurable<\/code> attribute is set to false (line 7), it presents from:<\/p>\n<ul>\n<li>Deleting object property (lines: 27-29),<\/li>\n<li>Modifying other <code>descriptor<\/code> attributes (lines: 19-22 &amp; 32-34). One exeption is <code>writable<\/code> attribute can be set to <code>false<\/code> (line 33) if it was originally set to <code>true<\/code> (line 6). Modification of all other descriptor setting will through <code>TypeError<\/code> (setting the same value does not throw any error).<\/li>\n<\/ul>\n<p>To make a object property <em>immutable<\/em>,\u00a0 both of its\u00a0 <code>configurable<\/code> and <code>writable<\/code> attributes should be set to <code>false<\/code>.<\/p>\n<p class=\"tip icon-note\"><strong>Tip<\/strong>: Similar to <code>writable<\/code> attribute, <code>configurable<\/code> attribute change is ONE way only and can&#8217;t be changed back.<\/p>\n<h5>Enumerable Attributes<\/h5>\n<p>When an object is created, the newly created object inherits certain methods through property inheritance (eg. <code>object.key()<\/code> method). Most object property are enumerable (where values can be changed) although there is some non-enumerable property too. An enumerable property can be iterated using <code>for..in<\/code> statement or with <code>object.key()<\/code> method. An enumerable property can be verified by calling <code>property.enumerable<\/code>, which return <code>true<\/code> or <code>false<\/code>.<\/p>\n<p>In the following example adopted the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/defineProperty#Enumerable_attribute\" target=\"_blank\" rel=\"noopener\">MDN Documentation<\/a>, lets examine the <code>enumerable<\/code> attribute in more detail.<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/ Create MyCar object\nlet myCar = {}; \/\/empty object\n\/\/add property &amp; assign value \nObject.defineProperty(myCar, &#039;make&#039;, {\n  value: &#039;Toyota&#039;,\n  enumerable: true\n});\/\/ logs =&gt;{make: &quot;Toyota&quot;}\n\/\/add another property\nObject.defineProperty(myCar, &#039;year&#039;, {\n  value: 2018,\n  enumerable: false\n});\/\/logs {make: &quot;Toyota&quot;, year: 2018}\n\/\/ add model property without setting enumerable value\nObject.defineProperty(myCar, &#039;model&#039;, {\n  value: &#039;Corolla&#039;\n}); \/\/ enumerable default to false\n\n\/\/add property with dot notation\nmyCar.price = &#039;20K&#039;; \/\/ enumerable defaults to true\n\n\/\/iterate over myCar with for..in\nfor (var i in myCar) {\n  console.log(i);\n}\/\/ logs &#039;make&#039; and &#039;price&#039;\n\/\/OUTPUT\nmake\nprice\n\n\/\/access object.key()\nObject.keys(myCar); \/\/=&gt;  [&#039;make&#039;, &#039;price&#039;]\n\n\/\/access objectIsEnumerable() method\nmyCar.propertyIsEnumerable(&#039;make&#039;); \/\/=&gt; true\nmyCar.propertyIsEnumerable(&#039;year&#039;); \/\/=&gt; false\nmyCar.propertyIsEnumerable(&#039;model&#039;); \/\/=&gt; false\nmyCar.propertyIsEnumerable(&#039;price&#039;); \/\/=&gt; true<\/code><\/pre>\n<p>In the example above, an empty <code>myCar<\/code> object is created (line 2) and assign four properties <code>make<\/code>, <code>year<\/code>, <code>model<\/code> and <code>price<\/code> using <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/defineProperty\" target=\"_blank\" rel=\"noopener\"><code>object.defineProperty()<\/code><\/a> method (line: 4, 9 &amp; 14) and <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Learn\/JavaScript\/Objects\/Basics#Dot_notation\" target=\"_blank\" rel=\"noopener\">dot notation<\/a> method (line 18). For the <code>make<\/code> property, its <code>enumerable<\/code> attribute is set as <code>true<\/code> (line 6) and for <code>year<\/code> property, it is set as <code>false<\/code> (line 11). For the <code>model<\/code> property it is not explicitly defined (line 18) and which defaults to <code>true<\/code>.<\/p>\n<p class=\"tip icon-note\"><strong>Tip<\/strong>: Property explicitly defined with <code>enumerable<\/code> as <code>true<\/code> are only listed with <code>for..in<\/code> loop or <code>Object.keys()<\/code> method.<\/p>\n<p>When we iterate over <code>myCar<\/code> object with <code>for..in<\/code> loop (lines: 22-24), properties with <code>enumerable<\/code> attribute set to <code>true<\/code> (<code>make<\/code> in line 6, and <code>price<\/code> by default) are listed (lines: 26-27). Likewise, the same two properties (<code>make<\/code> &amp; <code>price<\/code>) are listed (line 30) with <code>Object.keys()<\/code> method too. Whether a property is enumerable or not could be verified using <code>Object.propertyIsEnumerable()<\/code> method as shown for <code>myCar<\/code> object (lines:33-36).<\/p>\n<h6>Use Case Example<\/h6>\n<p>Enumerable descriptor attribute determines whether object property are listed using for..in loop and Object.keys() method. In practice, enumerable attribute can be modified in the <a href=\"https:\/\/abdulapopoola.com\/2016\/11\/28\/understanding-javascript-property-descriptors-2\/\" target=\"_blank\" rel=\"noopener\">following cases<\/a>:<\/p>\n<ul>\n<li><em>JSON serialization<\/em>: <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/JSON\" target=\"_blank\" rel=\"noopener\">JSON<\/a> is a syntax allows serializing objects, arrays and other data types. Quoting from <a href=\"https:\/\/abdulapopoola.com\/2016\/11\/28\/understanding-javascript-property-descriptors-2\/\" target=\"_blank\" rel=\"noopener\">this<\/a> post \u2013 <em>objects are created based off JSON data retrieved over XHR calls. These objects are then enhanced with a couple of new properties. When POSTing the data back, developers create a new object with extracted properties<\/em>. If <code>enumerable<\/code> descriptor is set to <code>false<\/code>, then <code>JSON.stringify<\/code> would drop properties from the list, and vice versa.<\/li>\n<li><em>Mixins<\/em>: Quoting from <a href=\"https:\/\/abdulapopoola.com\/2016\/11\/28\/understanding-javascript-property-descriptors-2\/\" target=\"_blank\" rel=\"noopener\">this<\/a> post again: <em>Another application could be mixins which add extra behavior to objects. If a mixin has an enumerable\u00a0getter accessor property; then that calculated property will automatically show up in Object.keys and\u00a0for..in\u00a0loops. The\u00a0getter\u00a0will behave just like any property<\/em>.<\/li>\n<\/ul>\n<p>Revisiting the same <code>myCar<\/code> object created previously, lets define <code>enumerable<\/code> &amp; <code>configurable<\/code> attributes slightly different way and examine its <code>enumerabilty<\/code> with <code>JSON.stringify()<\/code> method as shown in the example below:<\/p>\n<pre class=\"line-numbers\"><code class=\"language-javascript\">\/\/create myCar &amp; assign property\nlet myCar = {\n    make: &#039;Toyota&#039;,\n    year: 2018\n};\n\/\/add property with Object.defineProperty()\nObject.defineProperty(myCar, &#039;model&#039;, {\n  value: &#039;Corolla&#039;,\n  enumerable: true,\n  configurable: true\n}); \/\/logs =&gt;{make: &quot;Toyota&quot;, year: 2018, model: &quot;Corolla&quot;}\n\n\/\/assign a car var for Object.keys()\nlet car = Object.keys(myCar);\n\/\/access value on console\nconsole.log(car); \/\/OUTPUT =&gt; [&quot;make&quot;, &quot;year&quot;, &quot;model&quot;]\n\/\/iterate keys with for..each\ncar.forEach(i =&gt; console.log(myCar[i]));\n\/\/OUTPUT\nToyota\n2018\nCorolla\n\n\/\/JSON stringify\nJSON.stringify(myCar);\n\/\/OUTPUT\n&quot;{&quot;make&quot;:&quot;Toyota&quot;,&quot;year&quot;:2018,&quot;model&quot;:&quot;Corolla&quot;}&quot;\n\n\/\/modify enumerable to false\nObject.defineProperty(myCar, &#039;model&#039;, {\n    enumerable: false\n});\n\/\/access object.key()\nObject.keys(myCar); \/\/=&gt; [&quot;make&quot;, &quot;year&quot;]\n\/\/JSON stringify\nJSON.stringify(myCar);\/\/=&gt;&quot;{&quot;make&quot;:&quot;Toyota&quot;,&quot;year&quot;:2018}&quot;<\/code><\/pre>\n<p>In the example above, <code>myCar<\/code> object was created and assigned two properties &#8211; <code>make<\/code> and <code>year<\/code> to it (lines: 2-5). It was\u00a0 demonstrated earlier that all the descriptor attributes (<code>writable<\/code>, <code>enumerable<\/code> and <code>configurable<\/code>) of such properties are set to <code>true<\/code> by default.<\/p>\n<p>Another property <code>&#039;year&#039;<\/code> was also added to the <code>myCar<\/code> object with <code>Object.defineProperty()<\/code> method and assigned <code>configurable<\/code> and <code>configurable<\/code> descriptor attributes to <code>true<\/code> (lines: 9-10). By default, descriptor attributes of properties created this way are set to <code>false<\/code> by default (eg. <code>writable<\/code> is set to <code>false<\/code> by default).<\/p>\n<p>Because the <code>enumerable<\/code> descriptor is set <code>true<\/code>, all the three properties of <code>myCar<\/code> object are listed (lines: 20-22) with <code>forEach<\/code> iteration (line 18). Likewise, all three properties are listed (line 27) with <code>JSON.stringify()<\/code> method too (line 25).<\/p>\n<p>Unlike other property descriptors, the <code>enumerable<\/code> attribute can be modified. When the <code>enumerable <\/code>descriptor of <code>model<\/code> property was set to <code>false<\/code> (line 31) it was dropped from output listings with both <code>Object.keys()<\/code> method (line 34 )as well as <code>JSON.stringify()<\/code> method (line 36).<\/p>\n<p class=\"note icon-tip\"><strong>Note<\/strong>: Modification in <code>enumerable<\/code> attribute is TWO way. Unlike the <code>writable<\/code> attribute, it can be changed from <code>false<\/code> to <code>true<\/code> and vice versa.<\/p>\n<p>The MDN documentation has a list of <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object#Methods_of_the_Object_constructor\" target=\"_blank\" rel=\"noopener\">methods of the object constructor<\/a> including the following methods for the property descriptors as listed <a href=\"https:\/\/javascript.info\/property-descriptors#sealing-an-object-globally\" target=\"_blank\" rel=\"noopener\">here<\/a>:<\/p>\n<ul>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/preventExtensions\">Object.preventExtensions(obj)<\/a>: Prevents adding properties to object.<\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/seal\">Object.seal(obj)<\/a>: Prevents to add\/remove properties, sets for all existing properties <code>configurable: false<\/code>.<\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/freeze\">Object.freeze(obj)<\/a>: It prevents to add\/remove\/change properties, sets for all existing properties <code>configurable: false, writable: false<\/code>.<\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/isExtensible\">Object.isExtensible(obj)<\/a>: Determines if extending of an object is allowed. Returns <code>false<\/code> if adding properties is prohibited, otherwise <code>true<\/code>.<\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/isSealed\">Object.isSealed(obj)<\/a>: Determines if an object is sealed. Returns <code>true<\/code> if adding\/removing properties is prohibited, and all existing properties have <code>configurable: false<\/code>.<\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/isFrozen\">Object.isFrozen(obj)<\/a>: Determines if an object was frozen. Returns <code>true<\/code> if adding\/removing\/changing properties is prohibited, and all current properties are <code>configurable: false, writable: false<\/code>.<\/li>\n<\/ul>\n<p class=\"note icon-note\"><strong>Note<\/strong>: The above listed methods are rarely used in practice.<\/p>\n<h5>Wrapping Up<\/h5>\n<p>In this learning-note, we discussed when objects are created either with <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Guide\/Working_with_Objects#Using_object_initializers\" target=\"_blank\" rel=\"noopener\">object initializers<\/a> or with static <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/defineProperty\" target=\"_blank\" rel=\"noopener\"><code>Object.defineProperty()<\/code><\/a> method, their property descriptor attributes are defined differently. Object property descriptors &#8211; <code>writable<\/code>, <code>enumerable<\/code>, <code>configurable<\/code> were discussed and how their modification affects property enumeration with <code>for..in<\/code> loop or <code>Object.keys()<\/code> method and their use in <code>JSON.stringify()<\/code> method. Other related but more advance topic <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Guide\/Working_with_Objects#Defining_getters_and_setters#Defining_getters_and_setters\" target=\"_blank\" rel=\"noopener\">Objects Getters and Setters<\/a> will be discussed separately.<\/p>\n<p>Next Topic: <a href=\"https:\/\/tinjurewp.com\/jsblog\/understanding-javascript-accessors-getters-setters\/\" target=\"_blank\" rel=\"noopener\">Understanding JavaScript Accessors: Getters &amp; Setters<\/a><\/p>\n<h5>Useful Resources &amp; Links<\/h5>\n<p>While preparing this post, I have referred the following references extensively. Visit original link for additional information.<\/p>\n<ul>\n<li><a href=\"https:\/\/hashnode.com\/post\/what-are-enumerable-properties-in-javascript-ciljnbtqa000exx53n5nbkykx\" target=\"_blank\" rel=\"noopener\">What are Enumerable properties in JavaScript?<\/a> | <a href=\"https:\/\/hashnode.com\/\" target=\"_blank\" rel=\"noopener\">Hashnode<\/a><\/li>\n<li><a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Object\/defineProperty\" target=\"_blank\" rel=\"noopener\">Object .define Property()<\/a> | MDN Documentation<\/li>\n<li><a href=\"http:\/\/exploringjs.com\/es6\/ch_oop-besides-classes.html#_property-attributes\" target=\"_blank\" rel=\"noopener\">Enumerability in ECAMAScript 6<\/a> in\u00a0 | <a href=\"http:\/\/2ality.com\/\" target=\"_blank\" rel=\"noopener\">2ality.com<\/a><\/li>\n<li><a href=\"https:\/\/javascript.info\/property-descriptors\" target=\"_blank\" rel=\"noopener\">Property flags and descriptors<\/a> | <a href=\"https:\/\/javascript.info\/\" target=\"_blank\" rel=\"noopener\">The Modern JavaScript tutorial<\/a><\/li>\n<li><a href=\"https:\/\/abdulapopoola.com\/2016\/11\/21\/deep-dive-into-javascript-property-descriptors\/\" target=\"_blank\" rel=\"noopener\">Deep dive into JavaScript Property\u00a0Descriptors<\/a> | <a href=\"https:\/\/abdulapopoola.com\" target=\"_blank\" rel=\"noopener\">CodeKraft<\/a><\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Note: This post is work-in-progress learning-note and still in active development and updated regularly. In a previous learning-post JavaScript Objects &#8211; The Basics, we discussed simple key:value object properties (values associated with properties). The value is one of the attribute of a property. Other attributes include enumerable, configurable and writable. These attributes further define an [&hellip;]<\/p>\n","protected":false},"author":3,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_crdt_document":"","footnotes":""},"categories":[4,35],"tags":[],"class_list":["post-4720","post","type-post","status-publish","format-standard","hentry","category-javascript","category-objects"],"_links":{"self":[{"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/posts\/4720","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/users\/3"}],"replies":[{"embeddable":true,"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/comments?post=4720"}],"version-history":[{"count":0,"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/posts\/4720\/revisions"}],"wp:attachment":[{"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/media?parent=4720"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/categories?post=4720"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learncode.tinjurewp.com\/wp-json\/wp\/v2\/tags?post=4720"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}