207

I just heard about the JavaScript methods freeze and seal, which can be used to make any Object immutable.

Here's a short example how to use it:

var o1 = {}, o2 = {};
Object.freeze(o2);

o1["a"] = "worked";
o2["a"] = "worked";

alert(o1["a"]);   //prints "worked"
alert(o2["a"]);   //prints "undefined"

What is the difference between freeze and seal? Can they increase performance?

nalply
  • 26,770
  • 15
  • 78
  • 101
maja
  • 17,250
  • 17
  • 82
  • 125
  • 7
    Just a note to anyone looking at this question, the accepted answer is factually incorrect. @tungd's answer is correct. – Bjorn Aug 23 '14 at 23:03
  • 2
    Another note, there's also `Object.preventExtensions` in addition to `Object.seal` and `Object.freeze`. `Object.preventExtensions` just prevents new items from being added to an object. You can delete, configure, and change the values of properties on objects that had their extensibility turned off with `Object.preventExtensions`. – Bjorn Aug 23 '14 at 23:06
  • 1
    Recent update: https://v8.dev/blog/v8-release-76#frozen%2Fsealed-array-improvements – Mike Aug 27 '19 at 07:33

10 Answers10

228

Object.seal

  • It prevents adding and/or removing properties from the sealed object; using delete will return false
  • It makes every existing property non-configurable: they cannot be converted from 'data descriptors' to 'accessor descriptors' (and vice versa), and no attribute of accessor descriptors can be modified at all (whereas data descriptors can change their writable attribute, and their value attribute if writeable is true).
  • Can throw a TypeError when attempting to modify the value of the sealed object itself (most commonly in strict mode)

Object.freeze

  • Exactly what Object.seal does, plus:
  • It prevents modifying any existing properties

Neither one affects 'deep'/grandchildren objects. E.g., if obj is frozen, obj.el can’t be reassigned, but the value of obj.el could be modified, e.g. obj.el.id can be changed.


Performance:

Sealing or freezing an object may affect its enumeration speed, depending on the browser:

  • Firefox: enumeration performance is not impacted
  • IE: enumeration performance impact is negligible
  • Chrome: enumeration performance is faster with sealed or frozen objects
  • Safari: sealed or frozen objects enumerate 92% slower (as of 2014)

Tests: Sealed objects, Frozen objects.

maja
  • 17,250
  • 17
  • 82
  • 125
Niccolò Campolungo
  • 11,824
  • 4
  • 32
  • 39
  • 2
    Can you talk about why we would ever use these methods? Just because we can? – Alan Dong Aug 01 '14 at 21:59
  • 3
    In the future I think they're going to be used a lot (if optimized correctly) when developing a library/framework. They allow you to prevent the user to (even unintentionally) break your code (and, as stated in the answer, optimizations should lead to great speed improvements). But this is pure speculation :) – Niccolò Campolungo Aug 01 '14 at 22:17
  • 2
    This answer has many factual errors. For one, `seal` also makes existing properties non-configurable, see http://jsfiddle.net/btipling/6m743whn/ Number 2, you can still edit, that is change the values of existing properties on a sealed object. – Bjorn Aug 23 '14 at 23:02
  • I think you misunderstood non-configurable VS defining propreties. @Bjorn: you forgot to add the writable descriptor. Thus seal() will let you modify it. By default, defineProprety() will put it in readable mode only. Check this: http://jsfiddle.net/6m743whn/3/. Freeze won't let you do that. The answer is pretty correct according to the documentation. The short answer from tungd is very good to understand what are the use-cases of both functions. This answer is good too. – Yves Lange Feb 05 '15 at 10:41
  • 8
    FWIW, frozen and sealed objects are now faster than their unfrozen and unsealed counterparts in Chrome Canary v43.0.2317.0. – gx0r Feb 28 '15 at 22:57
  • 2
    @AlanDong A bit late in coming, but here is why you want to lock down an object.One of JavaScript’s features is that you can add a property any time you like; you can also do this _accidentally_ by mis-typing. Many of my students have tried to add an event handler called `onClick` or `onlick` and wondered why it’s not working. If JavaScript throws an error, then that’s one less thing to get wrong. Secondly, this allows you to implement constant properties on an object which prevents changes. This is particularly useful on object methjods. – Manngo Nov 25 '17 at 08:37
  • Your links to the performance tests are broken with `something went wrong` – Ferrybig Feb 02 '18 at 15:34
  • Weird that they are actually nearly twice as slow in safari, how about in the `V8 engine` / `NodeJs` ? – Sadra M. Jul 25 '21 at 11:38
184

I wrote a test project which compares these 3 methods:

  • Object.freeze()
  • Object.seal()
  • Object.preventExtensions()

My unit tests cover CRUD cases:

  • [C] add new property
  • [R] read existed property
  • [U] modify existed property
  • [D] remove existed property

Result:

enter image description here

Boghyon Hoffmann
  • 17,103
  • 12
  • 72
  • 170
piecioshka
  • 4,752
  • 2
  • 20
  • 29
  • 4
    This is brilliant. Does UPDATE take into account modifying (via defineProperty) the descriptor attributes e.g. configurable, enumerable, writable? – Drenai Sep 22 '17 at 00:13
  • I always though that DOM objects should be sealed (after polyfills, of course). That would help to prevent a lot of typo errors. – Manngo Nov 25 '17 at 08:49
  • @Manngo You can seal your DOM objects. Simply create a `DEBUGMODE` variable and set it to `true`. Then, do `if (DEBUGMODE) { ... }`. In the `...`, put your functionality for ensuring all DOM objects are always sealed. Then, when you are ready to distribute your webpage script, change `DEBUGMODE` to `false`, run your script through the closure compiler, and distribute it. It's as simple as that. – Jack G Sep 05 '18 at 16:53
  • @JackGiffin Thanks for the comment. I was just saying that I always thought it would be a good idea. I have a lot of students who end up typing something like `element.onlick=something` and getting frustrated because it doesn’t work, but it’s not technically an error. – Manngo Sep 05 '18 at 19:53
  • 2
    @Lonely Then it wouldn’t spell CRUD. You’d have to settle for something like RUDE ;) – Manngo Sep 05 '18 at 21:14
  • the value of a frozen object can be updated if a given property is defined by an accessor descriptor: `Object.defineProperty(o, "k", ((v) => ({ set(_v) { v = _v}, get: () => v }))())` – marzelin Jan 13 '21 at 11:39
95

You can always looks these up in MDN. In short:

  • Freeze: makes the object immutable, meaning no change to defined property allowed, unless they are objects.
  • Seal: prevent addition of properties, however defined properties still can be changed.
tungd
  • 14,467
  • 5
  • 41
  • 45
15

I have created a simple table to compare the below functions and explain the difference between these functions.

  • Object.freeze()
  • Object.seal()
  • Object.preventExtensions()

table that explains the difference between the above three methods

Mike
  • 14,010
  • 29
  • 101
  • 161
Shwetabh Shekhar
  • 2,608
  • 1
  • 23
  • 36
14

Object.freeze() creates a frozen object, which means it takes an existing object and essentially calls Object.seal() on it, but it also marks all “data accessor” properties as writable:false, so that their values cannot be changed.

-- Kyle Simpson, You Don't Know JS - This & Object Prototypes

ggorlen
  • 44,755
  • 7
  • 76
  • 106
shmuli
  • 5,086
  • 4
  • 32
  • 64
5

I was looking at the differences between Freeze and Seal in ECMAScript 5 and created a script to clarify the differences. Frozen creates an immutable object including data and structure. Seal prevents changes to the named interfaces - no adds, deletes - but you can mutate the object and redefine the meaning of its interface.

function run()
{
    var myObject = function() 
    { 
        this.test = "testing"; 
    }

    //***************************SETUP****************************

    var frozenObj = new myObject();
    var sealedObj = new myObject();

    var allFrozen = Object.freeze(frozenObj);
    var allSealed = Object.seal(sealedObj);
    alert("frozenObj of myObject type now frozen - Property test= " + frozenObj.test);
    alert("sealedObj of myObject type now frozen - Property test= " + sealedObj.test);

    //***************************FROZEN****************************

    frozenObj.addedProperty = "added Property"; //ignores add
    alert("Frozen addedProperty= " + frozenObj.addedProperty);
    delete frozenObj.test; //ignores delete
    alert("Frozen so deleted property still exists= " + frozenObj.test);
    frozenObj.test = "Howdy"; //ignores update
    alert("Frozen ignores update to value= " + frozenObj.test);
    frozenObj.test = function() { return "function"; } //ignores
    alert("Frozen so ignores redefinition of value= " + frozenObj.test);

    alert("Is frozen " + Object.isFrozen(frozenObj));
    alert("Is sealed " + Object.isSealed(frozenObj));
    alert("Is extensible " + Object.isExtensible(frozenObj));

    alert("Cannot unfreeze");
    alert("result of freeze same as the original object: " + (frozenObj === allFrozen).toString());

    alert("Date.now = " + Date.now());

    //***************************SEALED****************************

    sealedObj.addedProperty = "added Property"; //ignores add
    alert("Sealed addedProperty= " + sealedObj.addedProperty);
    sealedObj.test = "Howdy"; //allows update
    alert("Sealed allows update to value unlike frozen= " + sealedObj.test);
    sealedObj.test = function() { return "function"; } //allows
    alert("Sealed allows redefinition of value unlike frozen= " + sealedObj.test);
    delete sealedObj.test; //ignores delete
    alert("Sealed so deleted property still exists= " + sealedObj.test);
    alert("Is frozen " + Object.isFrozen(sealedObj));
    alert("Is sealed " + Object.isSealed(sealedObj));
    alert("Is extensible " + Object.isExtensible(sealedObj));

    alert("Cannot unseal");
    alert("result of seal same as the original object: " + (sealedObj === allSealed).toString());

    alert("Date.now = " + Date.now());
}
Jaycee
  • 3,098
  • 22
  • 31
4

I know I may be little late but

  • Similarity: both of them are used for creating non extensible objects.
  • Difference : In Freeze configurable , enumerable and writable attributes of the object are set to false. where as in Sealed writable attribute is set to true and rest of the attributes are false.
Faisal Naseer
  • 4,110
  • 1
  • 37
  • 55
3

You can now force a single object property to be frozen instead of freezing the whole object. You can achieve this with Object.defineProperty with writable: false as a parameter.

var obj = {
    "first": 1,
    "second": 2,
    "third": 3
};
Object.defineProperty(obj, "first", {
    writable: false,
    value: 99
});

In this example, obj.first now has its value locked to 99.

jaggedsoft
  • 3,858
  • 2
  • 33
  • 41
1

I wrote about this in my open-source e-book. It has a section about object restrictions https://github.com/carltheperson/advanced-js-objects/blob/main/chapters/chapter-3.md#object-restrictions

To summarize:

This table shows the hierarchy of restrictions: Table of restrictions

Object.preventExtensions fail example

const obj = { a: "A", b: "B" }
Object.preventExtensions(obj)

obj.c = "C" // Failure

console.log(obj) // { a: "A", b: "B" }

Object.seal fail example

const obj = { a: "A", b: "B" }
Object.seal(obj)

delete obj.a // Failure
obj.c = "C" // Failure

console.log(obj) // { a: "A", b: "B" }

Object.freeze fail example

const obj = { a: "A", b: "B" }
Object.freeze(obj)

delete obj.a // Failure
obj.b = "B2" // Failure
obj.c = "C" // Failure

console.log(obj) // { a: "A", b: "B" }

Note: How they "fail" depends if your code is running in strict mode or not.

  • Strict mode = error
  • Not in strict mode = silent fail
CarlThePerson
  • 493
  • 4
  • 8
0

preventExtensions is an Object method which prevents addition of any new property to an object

seal is an Object method which prevents addition and deletion of any property in an object

freeze is an Object method which prevents addition, deletion and update of any property of an object

There are also methods isExtensible, isSealed and isFrozen on Object to check

Object.preventExtensions(obj);
Object.isExtensible(obj);       // false
Object.seal(obj);
Object.isSealed(obj);            // true
Object.freeze(obj);
Object.isFrozen(obj);       // true
Tawseef Bhat
  • 370
  • 4
  • 12