0

I wanted to have an object field that is immutable. I've tried:

const a = 1;
var o = {
   x: 'This is mutable',
   y: a // This should not be mutable.
};
o.y = 'Changed';
console.log(o);

Field y gets re-assigned.
Is there any way to make this work?

10
  • You probably want to check stackoverflow.com/questions/9772307/… Commented Feb 22, 2018 at 10:32
  • Have you looked at Object.freeze()? You'd have to define your object beforehand, and then freeze it which is slightly different from what you have. Or Object.seal()? Commented Feb 22, 2018 at 10:33
  • @Andy the thing is that freeze() "locks" all the object properties Commented Feb 22, 2018 at 10:35
  • Question title "Is it possible to have a const object property?" kinda contradicts the question itself. Do you want to freeze object property or set a property that is not configurable (Uncaught SyntaxError: Identifier 'x' has already been declared at :1:1) Commented Feb 22, 2018 at 10:36
  • 1
    Not sure I understand the error message, where in that code snippet has x been declared?. When do you get that message? Commented Feb 22, 2018 at 10:36

3 Answers 3

3

Use Object.defineProperty() and set configurable as false.

var o = {
    x: 'This is mutable'
};
Object.defineProperty(o, "y", { configurable: false, writable: false });

console.log(o);

o.y will behave as if Object.freeze were called on it separately.

Sign up to request clarification or add additional context in comments.

Comments

2

If you want to have a simple object, you can use Object.defineProperty():

const tea = {};
Object.defineProperty(tea, 'bar', {
  value: 'unchanged',
  writable: false,
  configurable: false
});

console.log(tea.bar); // 'unchanged'
tea.bar = 'new value';
console.log(tea.bar); // 'unchanged'
delete tea.bar;
console.log(tea.bar); // 'unchanged'

Alternatively, if you need a class, you can use a getter along with a no-op setter:

class Foo {
  get bar() {
    return 'unchanged';
  }
  set bar(_) {}
};
const tea = new Foo();

console.log(tea.bar); // 'unchanged'
tea.bar = 'new value';
console.log(tea.bar); // 'unchanged'
delete tea.bar;
console.log(tea.bar); // 'unchanged'

6 Comments

delete foo.bar; will actually delete it, though.
You should add "use strict"; otherwise the set just silently fails.
@str Thanks for pointing that out, using a class fixes that issue.
@AluanHaddad Since a strong majority of new code today is either straight ES6 or transpiled, I think manually adding "use strict"; to SO answers is obsolete.
@Nit but there are so many stack snippets and people running code in their browser console. But especially for this question I think it's significant. That it throws is pretty important.
|
2
var obj = {a:1,b:2};

Object.defineProperty(obj,'b',{
    writable:false
});

obj.b = 3;

console.log(obj.b) //output 2
obj.a = 8; 
console.log(obj.a); //output 8

Comments

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.