Skip to content

Instantly share code, notes, and snippets.

@c7x43t
Last active June 28, 2018 12:28
Show Gist options
  • Save c7x43t/0de14c372d055275f3273454bc086ee8 to your computer and use it in GitHub Desktop.
Save c7x43t/0de14c372d055275f3273454bc086ee8 to your computer and use it in GitHub Desktop.
(function(global) {
var PARENT = "[[__PARENT__]]";
function Immutable(obj) {
if (obj instanceof Object) {
for (var keys = Object.keys(obj), i = 0; i < keys.length; i++) {
this[keys[i]] = obj[keys[i]];
}
}
if (obj !== false) Object.freeze(this);
return this;
}
Immutable.prototype.get = function(key) {
return this.getIn(key);
};
Immutable.prototype.getIn = function(key) {
var tmp, obj = this;
if (key instanceof Array) {
for (var i = 0, lastIndex = key.length - 1; i < key.length; i++) {
while (true) {
tmp = obj[key[i]];
//console.log({tmp:tmp,last:i===lastIndex,obj:obj,parent:obj.hasOwnProperty(PARENT)})
if (tmp !== undefined || !obj.hasOwnProperty(PARENT)) {
if (i === lastIndex) {
return tmp;
} else {
i++;
obj = tmp;
}
} else {
obj = obj[PARENT];
}
}
}
} else {
return this.getIn([key]);
}
};
Immutable.prototype.set = function(key, value, parent) {
var tmp = new Immutable(false);
tmp[key] = value;
//if(parent===undefined)
tmp[PARENT] = this;
Object.freeze(tmp);
return tmp;
};
Immutable.prototype.setIn = function(key, value, parent) {
if (key instanceof Array && key.length > 1) {
var tmpKey = [key.shift()];
var tmpNext = this.getIn(tmpKey);
var isImmutable = tmpNext instanceof this.constructor;
var next = isImmutable ? tmpNext : new this.constructor(tmpNext);
return this.set(tmpKey, next.setIn(key, value, isImmutable ? isImmutable : undefined), parent);
} else {
return this.set(key, value, parent);
}
};
global.Immutable = Immutable;
}(window));
//var imm=new Immutable({a:{b:{c:3}}});
//imm.setIn(["a","b","c"],4);
(function(global) {
var NOOP = () => {};
var PARENT = "[[__PARENT__]]";
function Immutable(obj) {
if (obj === undefined) return this;
for (var keys = Object.keys(obj), i = 0; i < keys.length; i++) {
this[keys[i]] = obj[keys[i]];
}
}
Immutable.prototype.get = function(key) {
if (key instanceof Array) {
return this.getIn(key);
}
var tmp, obj = this;
while (true) {
tmp = obj[key];
if (tmp || !obj.hasOwnProperty[PARENT]) {
return tmp;
} else {
obj = obj[PARENT];
}
}
};
// tailEndRecursionHashFunction:
function getHashFunction(object, keys, keyLength) {
var tmp = getHashed[keyLength - 1](object, keys, keyLength - 1);
return tmp.hasOwnProperty("get") ? tmp.get(keys[1]) : tmp[keys[1]];
}
var getHashed = new Array(20).fill(getHashFunction);
getHashed[0] = NOOP;
getHashed[1] = (object, keys) => object.get(keys[0]);
Immutable.prototype.getIn = function(key) {
return getHashed[key.length](this, key, key.length);
}
Immutable.prototype.set = function(key, value) {
var tmp = new Immutable();
tmp[key] = value;
tmp[PARENT] = this;
Object.freeze(tmp);
return tmp;
};
global.Immutable = Immutable;
}(window));
var value = Math.random();
var cycles = 5e6;
var time = performance.now();
var obj = new Immutable({
value
});
for (let i = 0; i < cycles; i++) {
const val = obj.get("value");
}
console.log({
get: performance.now() - time
});
//_________________________________
var value = Math.random();
var cycles = 5e6;
var time = performance.now();
var obj = new Immutable({
value
});
for (let i = 0; i < cycles; i++) {
const newValue = Math.random();
const val = obj.set("value", newValue);
}
console.log({
set: performance.now() - time
});
//_________________________________
var value = {
a: Math.random()
};
var cycles = 5e6;
var time = performance.now();
var obj = new Immutable({
value
});
for (let i = 0; i < cycles; i++) {
const val = obj.getIn(["value", "a"]);
}
console.log({
getIn: performance.now() - time
});
//_________________________________
// mock Immutable
function Immutable(obj){
var self=this;
function get(key){
return self[key];
};
function set(key,value){
return self[key]=value;
};
function isObject(obj){
return obj&&obj.constructor === Object;
}
if(!isObject(obj)){
obj={};
}
Object.defineProperty(obj,"get",{value:get});
Object.defineProperty(obj,"set",{value:set});
return obj;
}
var immutableHandler={
get: function(obj,key){
return obj.hasOwnProperty(key)?obj[key]:obj.hasOwnProperty("__Parent__")?obj.__Parent__[key]:undefined;
},
has: function(obj,key){
return obj.__Keys__.has(key)
}
}
function Immutable(obj){
//var clone={...obj};
var keys=new Set(Object.keys(obj));
var clone=Object.assign({},obj);
Object.defineProperty(clone,"__Keys__",{value:keys});
var proxy = new Proxy(clone, immutableHandler);
Object.freeze(makeIterable(proxy));
return proxy;
}
function NOOP(){}
function objectSubclass(obj){
var subObj={};
function collector(){};
for(var key of obj.__Keys__){
collector.prototype[key]=NOOP;
}
Object.setPrototypeOf(subObj,collector.prototype);
//collector.prototype=Object.create(Object.prototype);
return subObj;
}
function set(obj,key,value){
var newObj={};
function collector(){};
for(var key of obj.__Keys__){
collector.prototype[key]=NOOP;
}
Object.setPrototypeOf(newObj,collector.prototype);
//var newObj=new objectSubclass(obj);
var keys = new Set(obj.__Keys__);
keys.add(key+"");
Object.defineProperty(newObj,"__Keys__",{value:keys});
Object.defineProperty(newObj,"__Parent__",{value:obj});
newObj[key]=value;
var proxy=new Proxy(newObj, immutableHandler);
Object.freeze(makeIterable(proxy));
return proxy;
}
function makeIterable(imm){
imm[Symbol.iterator]=function*(){
for(var key of imm.__Keys__){
yield imm[key];
}
}
return imm;
}
var target={a:3};
var p = Immutable(target);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment