The magical life of JavaScript properties

Object properties are one of the fundamental structures of JavaScript.

Moreover those properties are a key to why people love JavaScript so much.

 

There is no better feeling than adding a property dynamically (e.g. in runtime),

var obj = {}
obj.someProperty = ‘nice’
obj.propertyTypeMethod = function(){
    //do something fancy
}

 

 

When dynamic properties meet the prototype chain it’s a festival...it's super easy to add a property in runtime to any exisitng instance of a specific 'Type' and to all its future instances via the prototpye mechanism:

MyArray.prototype.sum = function(){ //adding the sum property to the MyArray 'Type'
       for (var i = 0, sum = 0 ; i != this.length; ++i) {
                    var n = this[i];
                    if(!isNaN(n)) {
                                    sum += n;
                    }
      }
      return sum;
};
MyArray.prototype.avg = function(){
            return (this.sum() / this.length);
};

 

However, properties in JavaScript are much more complex than that, let’s review the magical life of properties

It will be a true statement to say that all the properties that are not built-ins have been added dynamically in runtime, think how a constructor works..

 

Properties have few attributes that some javascript developers are not aware of such as configurability, setter and getter, writability and enumerability.

In order to set those attributes one can define/redfine property via the Object.defineProperty(obj,key,descriptor) ‘static’ method.

Object.defineProperty receives 3 arguments, the object that own the property, the property key and the descriptor that enable us to control the property and a better way than ever before.

The descriptor itself is an object that has few properties, let’s review those properties

  • ‘configurable’, boolean that indicates whether the characteristics below(properties of the descriptor object) can be modified in runtime (e.g. via code).
var obj = {}
Object.defineProperty(obj, 'prop', {‘configurable’ : false});
//any attempt to change the descriptor will throw TypeError..
//any attempt to delete the 'prop' property will do nothing..

 

the default is false.

  • ‘value’, as it sounds, the value of the property, so one can just add a new property dynamically
var obj = {}
Object.defineProperty(obj, 'prop', {value : 'nice'});
//similar to obj.prop = 'nice'

 

the default value is undefined

  • ‘set’ and ‘get’, set function that receives that value as an argument and can manipulate it before ‘saving’ it and a get function that can manipulate the value before returning it.

            

var obj = {}
Object.defineProperty(obj, 'prop', {'configurable' : true,'get':function(){   console.log('get') }
    ,set:function(val){ console.log('set:'+val) } });
obj.prop = 'xval';
var x = obj.prop;

 

the default is undefined for both, notice that in case you will access this.prop in the getter it will blow up your stack away, try to imagine why..

  • 'writable', boolean that indicates whether this property value can be changed
var obj = {}
Object.defineProperty(obj, 'prop', {'value':'nice',configurable' :
 true,'writable':false })
obj.prop = 'nice?'//ignore...

 

            the default is false

  • 'enumerable', boolean that indicates whether this property will get listed on a for-in loop or not ( as well as the Object.keys() property)
var cars = {}
Object.defineProperty(cars, "BMW", { value : 100 });
Object.defineProperty(cars, "FORD", { value : 122, enumerable:false });
Object.defineProperty(cars, "MAZDA", { value : 70 , enumerable:true});
for (var car in cars) {     
     console.log(car);   
} //will only log MAZDA
     

 

the default is false

           

Pay attention that the defaults are only apply when one define a property via the the defineProperty() methods, moreover the defaults when defining a new property in the traditional way are quite the opposite..

so if we change the last example abit we get an additional car, take a look:

var cars = {‘KIA’,30}
cars.NISSAN = 210
Object.defineProperty(cars, "BMW", { value : 100 });
Object.defineProperty(cars, "FORD", { value : 122, enumerable:false });
Object.defineProperty(cars, "MAZDA", { value : 70 , enumerable:true});
for (var car in cars) {     
              console.log(car);   
} //will only log KIA, NISSAN and MAZDA

 

Another interesting issue is re-defining, one can re-define properties and even built-in properties, this is a very powerful tool..for example setting all the built-ins as unconfigurable can be a very strong statement. an exception to that is the ‘Array.length’ property which can cause different behavior across different browsers..

It’s important to note that defineProperty() has been announced in ECMAScript 5, hence only modern browser versions support it to the full extent.

 

if one would like to query a specific property descriptor he/she can do that easily thanks to Object.getOwnPropertyDescriptor(), another sugar ball is the ability to define few properties at once via Object.defineProperties()

 

References and extra reading:

 [1] http://dmitrysoshnikov.com/ecmascript/es5-chapter-1-properties-and-property-descriptors/#more-1183

[2]

http://css.dzone.com/articles/javascript-properties

[3]

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty and https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples

 

This article has been written by Ohad Assulin

 

 

Labels: web
Comments
Roy Ling | ‎04-18-2013 06:52 PM

It’s important to note that defineProperty() has been announced in ECMAScript 5, hence only modern browser versions support it to the full extent.

Here http://kangax.github.io/es5-compat-table/ lists the ES5 support status by modern browsers.

mrohad | ‎04-20-2013 02:11 AM

Roy, 

I totally agree, thank you for this comment.

 

Leave a Comment

We encourage you to share your comments on this post. Comments are moderated and will be reviewed
and posted as promptly as possible during regular business hours

To ensure your comment is published, be sure to follow the Community Guidelines.

Be sure to enter a unique name. You can't reuse a name that's already in use.
Be sure to enter a unique email address. You can't reuse an email address that's already in use.
Type the characters you see in the picture above.Type the words you hear.
Search
Showing results for 
Search instead for 
Do you mean 
About the Author
Featured


Follow Us
The opinions expressed above are the personal opinions of the authors, not of HP. By using this site, you accept the Terms of Use and Rules of Participation.