Skip to content

Difference with Object.freeze #4

Description

@alexpods

Can you explain: how new record:

const xy = #{ x: 1, y: 2 }; // frozen value type
const xyz = #{ ...xy, z: 3 }; // functional extension

is different from:

const xy = Object.freeze({ x: 1, y: 2 });
const xyz = Object.freeze({ ...xy, z: 3 });

?

And how new tuple:

const xy = #[ x, y ]; // frozen value type
const xyz = #[ ...xy, z ]; // functional extension

is different from this:

const xy = Object.freeze([ x, y ]); // frozen value type
const xyz = Object.freeze([ ...xy, z ]); // functional extension

?

If they're not deep immutable, it's looks like there are no differences. I suspect new types have some performance gains, but don't understand how it can be achieved.

Activity

  1. jmorrell commented on Mar 11, 2015

    @jmorrell

    A couple of things from my understanding (might be wrong), mostly assuming the implementation in JS engines would be something like Immutablejs. There are probably more reasons that I'm unaware of.

    1. Value equality vs reference equality
    const x = Object.freeze([ 1, 2 ]);
    const y = Object.freeze([ 1, 2 ]);
    console.log(x === y); // false
    

    vs

    const x = #[ 1, 2 ];
    const y = #[ 1, 2 ];
    console.log(x === y); // true
    
    1. You can get additional memory optimizations in the implementation through structural sharing. In the first example above you have two arrays allocated. In the second example they are literally the same object. Lee Byron does a good job of explaining this in his ReactjsConf talk (start at 5 minutes)
    2. There is a cost to freezing objects. In the product I work on we recursively freeze all of the data while in dev mode, and it results in a considerable drop in performance vs prod where we don't freeze the objects.
    3. There is some wonkiness when working with frozen objects with regards to strict mode. In strict mode trying to modify a frozen object throws an error, while outside of strict mode it will fail silently.
  2. bcherny commented on May 6, 2015

    @bcherny

    @jmorrell this would be a significant departure from the way javascript preforms equality checks. The behavior should be the same for mutable and immutable reference types. ie.

    let a = [1, 2]
    let b = [1, 2]
    a == a // true
    b == b // true
    a == b // false
    
    let c = #[1, 2]
    let d = #[1, 2]
    c == c // true
    d == d // true
    c == d // false

    the only way to have the behavior you want is to use singletons under the hood. ie. when declaring d above, d would have a pointer to the same location in memory as c, so c == d would be true. this is similar to the way scala treats reference types, so that they behave like value types.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions