5

if I have an object like

let person = {
       firstName: 'Krishna',
       lastName: 'Jai',
       age: 12
}
person.firstName = 'Kumar';
console.log(person);

//output
Object { firstname: 'Kumar', lastName: 'Jai', age: 12 }

But I should not let any user to change the firstName of person. how to make firstName immutable so that its value cannot be overriden?

1
  • Well actually all of your object's properties already have immutable values by definition because they are of String type. The right phrase should be read only and non-configurable property. Commented Mar 17, 2017 at 16:47

3 Answers 3

14

If you already have a property in place, you can modify it's descriptor's writable property to false like that:

Object.defineProperty(person, 'firstName', {
      writable: false,
      configurable: false
});

configurable: false should be specified to prevent future modifications of the firstName property, e.g. changing writable back to true.

Read more here about property descriptors.

If you're defining a property that didn't exist before, then all descriptor properties are defaulted to false and the only things you need to specify are value and enumerable:

Object.defineProperty(person, "firstName", {
    value: "Krishna",
    enumerable: true
});
Sign up to request clarification or add additional context in comments.

2 Comments

Not quite sure I know what you mean by that, but applying the above to the OP's object definitely leaves firstName open to re-configuring (and therefore becoming writable again): jsfiddle.net/11fcmftd
...whereas if you add configurable: false, it protects it: jsfiddle.net/11fcmftd/1
5

You have a couple of options, but probably the simplest is to make a read-only, non-configurable property:

let person = {
    lastName: 'Jai',
    age: 12
};
Object.defineProperty(person, "firstName", {
    value: "Krishna",
    enumerable: true
});

The flags writable and configurable both default to false when, as above, you're defining a new property. (You don't have to make it enumerable, as far as that goes, but...)

Example:

let person = {
    lastName: 'Jai',
    age: 12
};
Object.defineProperty(person, "firstName", {
    value: "Krishna",
    enumerable: true
});
console.log("before: ", person.firstName);
person.firstName = "Mohinder";
console.log("after setting in loose mode:", person.firstName);
function foo() {
    "use strict";
    console.log("trying to set in strict mode:");
    person.firstName = "Mohinder"; // Error
}
foo();

Or if you want to apply the change after the fact, you need to specify the flags:

let person = {
    firstName: "Krishna",
    lastName: 'Jai',
    age: 12
};
Object.defineProperty(person, "firstName", {
    writable: false,
    configurable: false
});

Example:

let person = {
    firstName: "Krishna",
    lastName: 'Jai',
    age: 12
};
Object.defineProperty(person, "firstName", {
    writable: false,
    configurable: false
});
console.log("before: ", person.firstName);
person.firstName = "Mohinder";
console.log("after setting in loose mode:", person.firstName);
function foo() {
    "use strict";
    console.log("trying to set in strict mode:");
    person.firstName = "Mohinder"; // Error
}
foo();

12 Comments

The flags writable and configurable both default to false - yes, but only if the property being defined for the first time, correct? If it has already existed, the descriptor will be merged
This is neatly explained. Thanks you so much.
@T.J.Crowder, Well what do you know... - didn't understand what you meant
@Maximus: I think so, thanks. TIL that if configurable is false, I can still change writable from true to false, which is...just wrong. :-) (But clearly stated in Step 8.a.i in the spec. Bizarre.)
|
0

You could use a getter method and omit the setter.

let person = {
       get firstName() { return 'Krishna'; },
       lastName: 'Jai',
       age: 12
    };

person.firstName = 'Kumar';
console.log(person);

4 Comments

I prefer this method personally.
@evolutionxbox: Why? Why require a function call on every access to the property when there's no reason to do so?
Because... neatness. :P
In JS, this is not the right way to do this job since i can easily override the above code by adding a single line like Object.defineProperty(person, "firstName", {get : function(){ return "Nina Scholz"}});console.log(person.firstName)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.