Object.freeze() vs const
Asked Answered
Y

6

196

Object.freeze() seems like a transitional convenience method to move towards using const in ES6.

Are there cases where both take their place in the code or is there a preferred way to work with immutable data?

Should I use Object.freeze() until the moment all browsers I work with support const then switch to using const instead?

Yaron answered 14/10, 2015 at 11:25 Comment(5)
I've taken to using babeljs in my build process so I can mainly ignore compatibility issues such as these.Howrah
No - they do different things. const prevents reassignment (e.g. you can't const x = 1; x = 2); freeze prevents mutation (e.g. you can't Object.freeze(x); x.a = 2);Sills
Not sure if it makes sense to make this a new question or just tack it on here but I would also be curious if there any big differences between Symbols and Object.freeze? I feel they are also related (i.e. Symbols are evaluated as frozen from Object.isFrozen but they also are their own primitive data type...)Hebraist
The mutation is prevented only for the first level so you can't Object.freeze(x); x.a = 2, but you CAN Object.freeze(x); x.a.b = 2. See jsfiddle.net/antimojv/op6ea91w/8 . For a full freeze use ad hoc librariesRetrogress
I think meybe he meant "as const"? And you guys are misinterpreting what the OP actually meant.Jehial
J
323

const and Object.freeze are two completely different things.

const applies to bindings ("variables"). It creates an immutable binding, i.e. you cannot assign a new value to the binding.

Object.freeze works on values, and more specifically, object values. It makes an object immutable, i.e. you cannot change its properties.

Jaddo answered 14/10, 2015 at 14:25 Comment(4)
Basically, const is the new var; it's just block-scoped and prevents reassignment. You can use let, but really only need to if you're going to change the value that a variable points to, which makes sense for loop control/iterator variables and simple types like numbers and strings, but not for most uses of objects (including arrays). If you want an object/array whose contents cannot be changed, then besides declaring it with const you should also call Object.freeze() on it.Foreknow
const is NOT the new var, let is the new varStamm
It seems Object.freeze only works on object and NOT on values types. e.g. var age = 33; Object.freeze(age); age=34; //no problem age can still be changed without any problem.Reefer
@MuhammadShoaib: You are comparing apples and oranges. Object.freeze doesn't prevent you from assigning a different value to a variable, that's what const is for. Your example will show the same "problem" when you use an object: var age = {years: 33}; Object.freeze(age); age = {years: 34}; // no problem. Besides, primitive values are already immutable...Jaddo
P
114

In ES5 Object.freeze doesn't work on primitives, which would probably be more commonly declared using const than objects. You can freeze primitives in ES6, but then you also have support for const.

On the other hand const used to declare objects doesn't "freeze" them, you just can't redeclare the whole object, but you can modify its keys freely. On the other hand you can redeclare frozen objects.

Object.freeze is also shallow, so you'd need to recursively apply it on nested objects to protect them.

var ob1 = {
   foo : 1,
    bar : {
        value : 2   
    }
};
Object.freeze( ob1 );

const ob2 = {
   foo : 1,
    bar : {
        value : 2   
    }
}

ob1.foo = 4;  // (frozen) ob1.foo not modified
ob2.foo = 4;  // (const) ob2.foo modified

ob1.bar.value = 4;  // (frozen) modified, because ob1.bar is nested
ob2.bar.value = 4;  // (const) modified

ob1.bar = 4;  // (frozen) not modified, bar is a key of obj1
ob2.bar = 4;  // (const) modified

ob1 = {};  // (frozen) ob1 redeclared
ob2 = {}; // (const) ob2 not redeclared
Perdure answered 14/10, 2015 at 11:39 Comment(1)
This explanation cleared so many of my questions in one sweep! Regarding ob1.bar.value = 4; // (frozen) modified, because ob1.bar is nested: Is it because of the method's scope?Connotative
L
35

Summary:

const and Object.freeze() serve totally different purposes.

  • const is there for declaring a variable which has to assinged right away and can't be reassigned. variables declared by const are block scoped and not function scoped like variables declared with var
  • Object.freeze() is a method which accepts an object and returns the same object. Now the object cannot have any of its properties removed or any new properties added.

Examples const:

Example 1: Can't reassign const

const foo = 5;

foo = 6;

The following code throws an error because we are trying to reassign the variable foo who was declared with the const keyword, we can't reassign it.

Example 2: Data structures which are assigned to const can be mutated

const object = {
  prop1: 1,
  prop2: 2 
}

object.prop1 = 5;   // object is still mutable!
object.prop3 = 3;   // object is still mutable!

console.log(object);  // object is mutated

In this example we declare a variable using the const keyword and assign an object to it. Although we can't reassign to this variable called object, we can mutate the object itself. If we change existing properties or add new properties this will this have effect. To disable any changes to the object we need Object.freeze().

Examples Object.freeze():

Example 1: Can't mutate a frozen object

object1 = {
  prop1: 1,
  prop2: 2
}

object2 = Object.freeze(object1);

console.log(object1 === object2); // both objects are refer to the same instance

object2.prop3 = 3; // no new property can be added, won't work

delete object2.prop1; // no property can be deleted, won't work

console.log(object2); // object unchanged

In this example when we call Object.freeze() and give object1 as an argument the function returns the object which is now 'frozen'. If we compare the reference of the new object to the old object using the === operator we can observe that they refer to the same object. Also when we try to add or remove any properties we can see that this does not have any effect (will throw error in strict mode).

Example 2: Objects with references aren't fully frozen

const object = {
  prop1: 1,
  nestedObj: {
    nestedProp1: 1,
    nestedProp2: 2,
  } 
}


const frozen = Object.freeze(object);

frozen.prop1 = 5; // won't have any effect
frozen.nestedObj.nestedProp1 = 5; //will update because the nestedObject isn't frozen

console.log(frozen);

This example shows that the properties of nested objects (and other by reference data structures) are still mutable. So Object.freeze() doesn't fully 'freeze' the object when it has properties which are references (to e.g. Arrays, Objects).

Lesbianism answered 15/8, 2018 at 12:45 Comment(1)
Nice explanationDoerrer
C
14

Let be simple.

They are different. Check the comments on the code, that will explain each case.

Const - It is block scope variable like let, which value can not reassignment, re-declared .

That means

{
 const val = 10;  // you can not access it outside this block, block scope variable

}

console.log(val); // undefined because it is block scope 

const constvalue = 1;
constvalue = 2; // will give error as we are re-assigning the value;
const obj = { a:1 , b:2};

obj.a = 3;
obj.c = 4;
console.log(obj); // obj = {a:3,b:2,c:4} we are not assigning the value of identifier we can 
                  // change the object properties, const applied only on value, not with properties
obj = {x:1};     // error you are re-assigning the value of constant obj 
obj.a = 2 ;     // you can add, delete element of object

The whole understanding is that const is block scope and its value is not re-assigned.

Object.freeze: The object root properties are unchangeable, also we can not add and delete more properties but we can reassign the whole object again.

var x = Object.freeze({data:1,
    name:{
    firstname:"hero", lastname:"nolast"
    }
});

x.data = 12;  // the object properties can not be change but in const you can do
x.firstname ="adasd"; // you can not add new properties to object but in const you can do

x.name.firstname = "dashdjkha"; // The nested value are changeable 

//The thing you can do in Object.freeze but not in const

x = { a: 1};  // you can reassign the object when it is Object.freeze but const its not allowed

// One thing that is similar in both is, nested object are changeable

const obj1 = {nested :{a:10}};
var obj2 =  Object.freeze({nested :{a:10}});

obj1.nested.a = 20; // both statement works
obj2.nested.a = 20;

Thanks.

Commit answered 11/1, 2019 at 8:7 Comment(0)
T
12
var obj = {
  a: 1,
  b: 2
};
Object.freeze(obj);
obj.newField = 3; // You can't assign new field , or change current fields

The above example it completely makes your object immutable.

Lets look following example.

const obj = {
  a: 1,
  b: 2
};
obj.a = 13; // You can change a field
obj.newField = 3; // You can assign new field.

It won't give any error.

But If you try like that

const obj = {
      a: 1,
      b: 2
    };
obj = {
 t:4
};

It will throw an error like that "obj is read-only".

Another use case

const obj = {a:1};
var obj = 3;

It will throw Duplicate declaration "obj"

Also according to mozilla docs const explanation

The const declaration creates a read-only reference to a value. It does not mean the value it holds is immutable, solely that the variable identifier can not be reassigned.

This examples created according to babeljs ES6 features.

Talus answered 14/10, 2015 at 11:59 Comment(0)
H
-1

in ES6 const is more used than before and you cant define it again with another value you encounter an Error, on the other hand if you make an object freez you cant change or define its properties again, you face an Error again

Heptavalent answered 20/2 at 8:51 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Unbroken

© 2022 - 2024 — McMap. All rights reserved.