What are the benefits of not listing properties?

Enumeration is one of the three attributes of a property: writeability, enumeration, and configurability. My questions:

  • What is the advantage of creating properties not enumerable in JavaScript? I know that we hide a property, making them non-enumerable, but what is the advantage of hiding a property?
  • Can we access non-enumerable properties? If so, what is the advantage of making them non-enumerable?
  • Are all the predefined properties of objects given as non-enumerable? For example, if the Array pop and push properties are not enumerable?
+40
javascript prototype enumerable
Feb 20 '13 at 16:09
source share
3 answers

I think the main advantage is being able to control what is displayed when listing the properties of an object, such as for in or Object.keys() .

MDN explains this well with Object.defineProperty : https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

So usually, when people want to add a method to an Object , for example, a polyfill for some method that is not supported in older browsers, they modify .prototype . But this makes the property enumerable and confuses what is returned in the collection of loops / keys ( without using .hasOwnProperty ), which not everyone uses).

So, instead of something like:

 Object.prototype.myMethod = function () { alert("Ahh"); }; 

you can use Object.defineProperty to explicitly say that it cannot be enumerated:

 Object.defineProperty(Object.prototype, 'myMethod', { value: function () { alert("Ahh"); }, enumerable: false }); 

Thus, for example, when you use for (var key in obj) , "myMethod" will not be an enumerated element, and you do not have to worry about using .hasOwnProperty . The main problem is that some browsers, of course, do not support it: http://kangax.github.com/es5-compat-table/ and that not all libraries / code use it, so you can not always rely on external libraries / code for proper use and all the time.

You can access an enumerable property at any time, it simply will not appear when listing the properties of an object - this is the main point.

And I believe that all the "predefined" properties of objects are not enumerable. By this, I really mean only my own properties, not necessarily inherited or created. So, in your example pop and push will not be listed, but Array.prototype.indexOf will be if it is created as polyfill in an old browser that does not support this method ... which, of course, can be avoided by using Object.defineProperty , like my example is above. Another example is the length property, which is not enumerable.

Here is an example in general: http://jsfiddle.net/aHJ3g/

The use and definition of Object.keys is important: "Returns an array of the specified objects of their own enumerable properties in the same order as in the for-in loop (the difference is that the for-in loop enumerates the properties in the prototype chain). - from MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys

+36
Feb 20 '13 at 16:20
source share

Another important advantage that I see in it is that it prevents the public namespace from being polluted with the private properties of the object.

Suppose you created and published a powerful library called Cosmos . The user starts the Node interpreter and creates a new instance by calling the constructor:

 var Cosmos = require('Cosmos'); var cosmos = new Cosmos('my empire'); 

Now the user simply types Cosmos and press enter to find out which public API they support. Which one do you want to see?

 { name: 'my empire', grow: [Function: grow], addStar: [Function: addStar], beautify: [Function: beautify], implode: [Function: implode], destroy: [Function: destroy] } 

OR

 { _age: 25000, _size: 35000, _destroyed: false, name: 'my empire', _numStars: 200, _init: [Function: _init], grow: [Function: grow], _grow: [Function: _grow], addStar: [Function: addStar], _checkStatus: [Function: _checkStatus], beautify: [Function: beautify], implode: [Function: implode], destroy: [Function: destroy] } 
+12
Jul 28 '13 at 7:22
source share
  • By providing a property that is not enumerable, you can still get it. But when you apply a for for loop to an object, the non-enumerable property will not be iterated.
  • See the first point.
  • Inherited properties of inline objects (e.g. push, pop, toString ...) are not listed

     var o = {a:1, b:2, c:3} // a,b,c are enumerable properties o.propertyIsEnumerable("toString") // returns false, because it is a inherited property for(p in o) console.log(p); // this loop will print a,b and c but not toString or other inherited properies 
+2
Feb 20 '13 at 16:16
source share



All Articles