Giter VIP home page Giter VIP logo

alhambra's Introduction

Alhambra

Protect objects/arrays from mutation without deep cloning.

Alhambra uses Proxies and shallow clones to protect the "original" object from mutation. The "protected" object has the same behavior as the original object: getters, setters, methods, and the prototype chain act the same.

If you want to remove the Proxy wrappers from the protected object, use alhambra.release() on it.

Comparison to deep cloning

Alhambra

  • Pros:
    • Creation cost does not increase as size increases.
  • Cons:
    • Interaction cost of the clone is more expensive than the original.
    • Interaction cost increases as the nesting depth of properties increase. For example, getting clone.foo.bar is more expensive than getting clone.foo.

Deep clone

  • Pros:
    • Interaction (get, set, etc.) cost of the clone is the same as the original.
    • Interaction cost does not increase as size increases.
  • Cons:
    • Creation cost increases as size of original increases.

In other words

  • Alhambra is better when you "clone big/frequently and interact small/infrequently".
    • For example, if you clone an array of 10 million objects and only interact with a few objects.
  • Deep cloning is better when you "clone small/infrequently and interact big/frequently".
    • For example, if you clone an array of 10 million objects and iterate over the entire array.

Usage

npm install alhambra

Objects

Directly mutating an object's properties keeps the original unchanged.

const obj = { id: 1 };
const p = alhambra.protect(obj);

p.id = 2;

const newObj = alhambra.release(p);

console.log(obj.id === 1); // True
console.log(newObj.id === 2); // True

Nested properties are protected, too.

const obj = { foo: { bar: 1 } };
const p = alhambra.protect(obj);

p.foo.bar = 2;

const newObj = alhambra.release(p);

console.log(obj.foo.bar === 1); // True
console.log(newObj.foo.bar === 2); // True

The original object is returned when the protected object isn't changed.

const obj = { id: 1 };
const p = alhambra.protect(obj);
const newObj = alhambra.release(p);

console.log(obj === newObj); // True

Instantiation.

class Foo {
  constructor() {
    this.id = 1;
  }

  greet() {
    console.log('Hello!');
  }
}

const obj = new Foo();
const p = alhambra.protect(obj);

p.id = 2;
p.greet(); // Still works.

const newObj = alhambra.release(p);

console.log(obj.id === 1); // True
console.log(newObj.id === 2); // True

Arrays

Prototype methods work.

const alhambra = require('alhambra');
const arr = [1, 2, 3];
const p = alhambra.protect(arr);

p.push(4);

const newArr = alhambra.release(p);

console.log(arr.length === 3); // True
console.log(newArr.length === 4); // True

Nested array.

const alhambra = require('alhambra');
const obj = {
  foo: {
    arr: [1, 2, 3],
  },
};
const p = alhambra.protect(obj);

p.foo.bar.arr.push(4);

const newObj = alhambra.release(p);

console.log(obj.foo.arr.length === 3); // True
console.log(newObj.foo.arr.length === 4); // True

Arrays of objects

Unchanged objects keep the same reference.

const alhambra = require('alhambra');
const obj = {
  foo: {
    arr: [{ a: 1 }, { a: 2 }, { a: 3 }],
  },
};
const p = alhambra.protect(obj);

p.foo.arr[1].a = 100;

const reversed = alhambra.release(p);

console.log(reversed.foo.arr[0] === obj.foo.arr[0]); // True
console.log(reversed.foo.arr[1] === obj.foo.arr[1]); // False
console.log(reversed.foo.arr[2] === obj.foo.arr[2]); // True

Caveats

Mutations to the source can still affect the new object. This is because the protect() method is designed to protect the source, rather than new object.

const alhambra = require('alhambra');
const obj = { id: 1 };
const p = alhambra.protect(obj);

obj.id = 2;

const newObj = alhambra.release(p);

console.log(obj.id === 2); // True
console.log(newObj.id === 2); // True

alhambra's People

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.