Defining non-writable properties without Object.defineProperty?

2.5k Views Asked by At

So I know you can do this:

var obj = {};
Object.defineProperty(obj, 'staticProp', {
    value: 'I will never change',
    writable: 'false'
});

And I know you can do this:

var obj = {
    get gettableProp(){
        return 'gettable!'
    }
} 

Is there a way to define non-writable/enumerable/configurable properties declaratively instead of using Object.defineProperty(), the way you'd define a getter or setter?

The reason I ask is because I have a function that gets passed an object like this:

ObjectProcessor({
    // A bunch of properties
})

I'd really like to be able to keep that simple syntax for cases when I'd want to include non-writable or non-enumerable properties, rather than having to do

var obj = {}
Object.defineProperty(obj, 'staticProp', {
    value: 'I will never change',
    writable: 'false'
});
ObjectProcessor(obj);
3

There are 3 best solutions below

0
On BEST ANSWER

Is there a way to define non-writable/enumerable/configurable properties declaratively instead of using Object.defineProperty(), the way you'd define a getter or setter?

No.

(there is Object.defineProperties, but I guess that's not what you are looking for)

2
On

No, there is no other method (except for Object.defineProperties and Object.create that allow you to provide multiple of these descriptors).

I'd really like to be able to keep that simple syntax

Notice that Object.defineProperty returns the passed object, so you can simplify your code to

ObjectProcessor(Object.defineProperty({}, 'staticProp', {
    value: 'I will never change',
    writable: 'false'
}));

and avoid introducing that extra obj variable.

3
On

With a naming convention, you can build it into your ObjectProcessor:

var prefix = 'readonly_';

function ObjectProcessor(obj) {
    Object.keys(obj).filter(function (name) {
        // find property names which match your convention
        return name.indexOf(prefix) === 0;
    }).forEach(function (name) {
        // make the new property readonly
        Object.defineProperty(obj, name.substring(prefix.length), {
            value: obj[name],
            writable: false
        });

        // remove the old, convention-named property
        delete obj[name];
    });

    // remaining ObjectProcessor logic...
}

This lets you handle writable and readonly properties:

ObjectProcessor({
    readonly_id: 1,
    name: 'Foo'
});