ECMA5 features and why they might make sense


Today, I asked on LinkedIn “Under which circumstances I should use { enumerable : false } ? Just to prevent the appearance of the property in .keys()?”.

The answer: “A good example of something that shouldn’t be enumerable is the Array length property. It’s a property that shouldn’t be iterated over or treated as part of the collection. So, say you have a custom object that can be iterated through, but you also want to attach some metadata such as, for example, an Animals collection that has properties like .numberOfMammals, and .numberOfReptiles. You could still use Object.keys to iterate through all the animals, but you can also have properties that aren’t considered part of the collection.”

Consider these examples. The first one is implemented as a Map class and it’s kind of “static”. The second one inherits from Array prototype and adds the add method and both properties numberOfMammals and numberOfReptiles as well. Consider that both properties aren’t enumberable.

Actually the advantages of the second implementation are:

  • we can use the existing collection class: Array
  • people don’t need to know something about the proprietary implementation (like this.arr
    in the first example)
  • we are enabled to hide the implementation details by using enumerable=false

Note. You might have recognized that we implemented a new method add just to insert our data instead of the inherited push method. I would like to get rid of it… Is there a “beforePush” event so that I could set the properties numberOfMammals and numberOfReptiles properly?

Example 1 (strong typed):

function Map() {
    this.arr = [];
    this.numberOfMammals = 0;
    this.numberOfReptiles = 0;

    this.add = function (obj) {
        if (!obj.type) return null;
        if (obj.type == 'mammal') this.numberOfMammals++;
        else if (obj.type == 'reptile') this.numberOfReptiles++;
        else return null; //unknown
        this.arr.push(obj);
    }
}

var m = new Map();
m.add({
    type: 'mammal',
    name: 'dog'
});
m.add({
    type: 'reptile',
    name: 'turtle'
});

console.log(m.numberOfMammals);
console.log(m.numberOfReptiles);
for (var i = 0; i < m.arr; i++) {
    console.log(m.arr[i]);
}

Example 2 (using new ECMA5 features):

var prot = [];
prot.add = function (obj) {
    if (!obj.type) return null;
    if (obj.type == 'mammal') this.numberOfMammals++;
    else if (obj.type == 'reptile') this.numberOfReptiles++;
    else return null; //unknown
    this.push(obj);
};
var obj = Object.create(prot, {
    numberOfReptiles: {
	value : 0,
	configurable: true,
	writable: true,
	enumerable : false
    },
    numberOfMammals: {
	value : 0,
	configurable: true,
	writable: true,
	enumerable : false
    }

});
obj.add({
    type: 'mammal',
    name: 'dog'
});
obj.add({
    type: 'reptile',
    name: 'turtle'
});

Object.keys(obj).forEach( function(key) {
	console.log( obj[key] );
} );
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s