JavaScript ES5: the Object.defineProperty() method

Feb 09, 2017

We can use the form: varable.property to get and set the value of an object: var obj = {a:1} in JavaScript. This is the most common and convenient way we code in JS, however the property that is created in this way can be easily modified and is enumerable. The Object.defineProperty() allows precise addition to or modification of a property on an object. It has been widely used in some popular two-way binding JS libraries.

Syntax

The Object.defineProperty() accepts three arguments:

Object.defineProperty(obj, prop, descriptor)

Arguments

Parameter name Type Description
obj Object The object on which to define the property
prop String The name of the property to be defined or modified
descriptor Object The descriptor of the property to be defined or modified

Return Value

The object that was passed to the function.

Descriptor

The third parameter accepts an object to describe the details of the property to be defined or modified. Following attributes are allowed.

Attribute Description Default value
configurable Whether the property can be deleted and its descriptor can be changed false
enumerable Whether the property can be enumerated using for...in and be listed using Object.keys(obj) false
value The value associated with the property undefined
writable Whether the value associated with the property can be changed with an assignment operator ("=") false
get A function which serves as a getter for the property undefined
set A function which serves as a setter for the property undefined

Configurable & Enumerable

  • Once the configurable attribute is set to false, the Object.defineProperty() method can no longer change the attributes of the property and the property cannot be deleted.
  • If the enumerable attribute is set to true, then the property can be enumerated using for...in and shows up in the result of Object.keys().
var obj = {};

Object.defineProperty(obj, 'name', {
    value: 'John',
    configurable: true,
    enumerable: true
});
Object.keys(obj); // Array [ "name" ]

Object.defineProperty(obj, 'name', {
    enumerable: false,
    configurable: false
});
Object.keys(obj); // Array [  ]

Object.defineProperty(obj, 'name', {
    enumerable: true
}); // TypeError: can't redefine non-configurable property "name"
delete obj.name; // false
obj.name; // "John"

Value & Writable

When the writable attribute is set to false, the value associated with the property cannot be be changed with an assignment operator, but we can still use Object.defineProperty() method to reassign the value.

var obj = {};
Object.defineProperty(obj, 'name', {
    value: 'John',
    writable: false,
    configurable: true
});
console.log(obj.name); // "John"

obj.name = 'Marry';
console.log(obj.name); // "John"

Object.defineProperty(obj, 'name', {
    value: 'Marry'
});
console.log(obj.name); // "Marry"
var obj = {};
obj.name = 'John';

Is equivalent to:

var obj = {};
Object.defineProperty(obj, 'name', {
    value: 'John',
    writable: true,
    configurable: true,
    enumerable: true
});

Getter && Setter

  1. get function is called when getting the property value, the function returns the property value
  2. set function is called when setting the property value using an assignment operator ("=")
  3. setter and getter functions cannot coexist with the value attribute
var Person = function(name) {
    var nameValue;
    Object.defineProperty(this, 'name', {
        set: function(name) {
            nameValue = name.substr(0, 1).toUpperCase().concat(name.substring(1));
        },
        get: function() {
            return nameValue;
        }
    });
    this.name = name;
};
var john = new Person('john');
console.log(john.name); // "John"

Browser compatibility

  • Chrome 5 +
  • FireFox 4 +
  • IE 9+
  • Opera 11.60 +
  • Safari 5.1 +

References

Keywords:

JavaScriptES5