immutable-assign
Advanced tools
Comparing version 1.0.23 to 1.0.24
@@ -5,2 +5,4 @@ | ||
(function () { | ||
"use strict"; | ||
var ARRAY_LENGTH, DEEP_PATH, INITIAL_ARRAY, INITIAL_OBJECT, Immutable, R, Seamless, _, _addResult, _allTests, _getIn, _solImmutableJs, _solImmutableSeamless, _solImmutableTimm, _solMutable, _test, _toggle, _verify, chalk, i, n, ref, timm; | ||
@@ -20,5 +22,9 @@ | ||
iassign = require("../src/iassign"); | ||
var _isDevel = false; | ||
INITIAL_OBJECT = { | ||
var deepFreeze = require("deep-freeze"); | ||
var iassign = require("../src/iassign"); | ||
var INITIAL_OBJECT = { | ||
toggle: false, | ||
@@ -45,7 +51,7 @@ b: 3, | ||
DEEP_PATH = ['d', 'd9', 'b', 'b', 'b']; | ||
var DEEP_PATH = ['d', 'd9', 'b', 'b', 'b']; | ||
ARRAY_LENGTH = 1000; | ||
var ARRAY_LENGTH = 1000; | ||
INITIAL_ARRAY = new Array(ARRAY_LENGTH); | ||
var INITIAL_ARRAY = new Array(ARRAY_LENGTH); | ||
@@ -59,6 +65,8 @@ for (n = i = 0, ref = ARRAY_LENGTH; 0 <= ref ? i < ref : i > ref; n = 0 <= ref ? ++i : --i) { | ||
R = 5e5; | ||
W = R / 5; | ||
var INITIAL_DEEP_ARRAY = [0, 1, 2, INITIAL_ARRAY, [5, 6, 7]]; | ||
_getIn = function (obj, path) { | ||
var R = 5e5; | ||
var W = R / 5; | ||
var _getIn = function (obj, path) { | ||
var j, key, len, out; | ||
@@ -73,3 +81,3 @@ out = obj; | ||
_solMutable = { | ||
var _solMutable = { | ||
init: function () { | ||
@@ -112,4 +120,7 @@ return _.cloneDeep(INITIAL_OBJECT); | ||
}, | ||
initArr: function () { | ||
return _.cloneDeep(INITIAL_ARRAY); | ||
initArr: function (array) { | ||
if (!array) { | ||
array = INITIAL_ARRAY; | ||
} | ||
return _.cloneDeep(array); | ||
}, | ||
@@ -122,8 +133,19 @@ getAt: function (arr, idx) { | ||
return arr; | ||
}, | ||
getAtDeep: function (arr, idx1, idx2) { | ||
return arr[idx1][idx2]; | ||
}, | ||
setAtDeep: function (arr, idx1, idx2, val) { | ||
arr[idx1][idx2] = val; | ||
return arr; | ||
} | ||
}; | ||
_solIassign = { | ||
var _solObjectAssign = { | ||
init: function () { | ||
return _.cloneDeep(INITIAL_OBJECT); | ||
var obj = _.cloneDeep(INITIAL_OBJECT); | ||
if (_isDevel) { | ||
obj = deepFreeze(obj); | ||
} | ||
return obj; | ||
}, | ||
@@ -134,2 +156,90 @@ get: function (obj, key) { | ||
set: function (obj, key, val) { | ||
if (obj[key] === val) | ||
return obj; | ||
obj = Object.assign({}, obj); | ||
obj[key] = val; | ||
return obj; | ||
}, | ||
getDeep: function (obj, key1, key2) { | ||
return obj[key1][key2]; | ||
}, | ||
setDeep: function (obj, key1, key2, val) { | ||
if (obj[key1][key2] === val) | ||
return obj; | ||
obj = Object.assign({}, obj); | ||
obj[key1] = Object.assign({}, obj[key1]); | ||
obj[key1][key2] = val; | ||
return obj; | ||
}, | ||
getIn: _getIn, | ||
setIn: function (obj, path, val) { | ||
obj = Object.assign({}, obj); | ||
var prop = obj; | ||
for (var i = 0; i < path.length; ++i) { | ||
var pathPart = path[i]; | ||
if (i < path.length - 1) { | ||
prop[pathPart] = Object.assign({}, prop[pathPart]); | ||
prop = prop[pathPart]; | ||
} | ||
else { | ||
prop[pathPart] = val; | ||
} | ||
} | ||
return obj; | ||
}, | ||
merge: function (obj1, obj2) { | ||
return Object.assign({}, obj1, obj2); | ||
}, | ||
initArr: function (array) { | ||
if (!array) { | ||
array = INITIAL_ARRAY; | ||
} | ||
var obj = _.cloneDeep(array); | ||
if (_isDevel) { | ||
obj = deepFreeze(obj); | ||
} | ||
return obj; | ||
}, | ||
getAt: function (arr, idx) { | ||
return arr[idx]; | ||
}, | ||
setAt: function (arr, idx, val) { | ||
if (arr[idx] === val) | ||
return arr; | ||
arr = arr.slice(0); | ||
arr[idx] = val; | ||
return arr; | ||
}, | ||
getAtDeep: function (arr, idx1, idx2) { | ||
return arr[idx1][idx2]; | ||
}, | ||
setAtDeep: function (arr, idx1, idx2, val) { | ||
if (arr[idx1][idx2] === val) | ||
return arr; | ||
arr = arr.slice(0); | ||
arr[idx1] = arr[idx1].slice(0); | ||
arr[idx1][idx2] = val; | ||
return arr; | ||
}, | ||
}; | ||
var _solIassign = { | ||
init: function () { | ||
var obj = _.cloneDeep(INITIAL_OBJECT); | ||
if (_isDevel) { | ||
obj = deepFreeze(obj); | ||
} | ||
return obj; | ||
}, | ||
get: function (obj, key) { | ||
return obj[key]; | ||
}, | ||
set: function (obj, key, val) { | ||
// Paul Note | ||
@@ -148,2 +258,3 @@ if (obj[key] === val) | ||
setDeep: function (obj, key1, key2, val) { | ||
// Paul Note | ||
if (obj[key1][key2] === val) | ||
@@ -186,4 +297,12 @@ return obj; | ||
}, | ||
initArr: function () { | ||
return _.cloneDeep(INITIAL_ARRAY); | ||
initArr: function (array) { | ||
if (!array) { | ||
array = INITIAL_ARRAY; | ||
} | ||
var obj = _.cloneDeep(array); | ||
if (_isDevel) { | ||
obj = deepFreeze(obj); | ||
} | ||
return obj; | ||
}, | ||
@@ -194,2 +313,3 @@ getAt: function (arr, idx) { | ||
setAt: function (arr, idx, val) { | ||
// Paul Note | ||
if (arr[idx] === val) | ||
@@ -202,2 +322,19 @@ return arr; | ||
); | ||
}, | ||
getAtDeep: function (arr, idx1, idx2) { | ||
return arr[idx1][idx2]; | ||
}, | ||
setAtDeep: function (arr, idx1, idx2, val) { | ||
if (arr[idx1][idx2] === val) | ||
return arr; | ||
return iassign( | ||
arr, | ||
function (arr, ctx) { return arr[ctx.idx1][ctx.idx2]; }, | ||
function (prop) { return val; }, | ||
{ | ||
idx1: idx1, | ||
idx2: idx2 | ||
} | ||
) | ||
} | ||
@@ -207,3 +344,3 @@ }; | ||
_solImmutableTimm = { | ||
var _solImmutableTimm = { | ||
init: function () { | ||
@@ -231,4 +368,7 @@ return _.cloneDeep(INITIAL_OBJECT); | ||
}, | ||
initArr: function () { | ||
return _.cloneDeep(INITIAL_ARRAY); | ||
initArr: function (array) { | ||
if (!array) { | ||
array = INITIAL_ARRAY; | ||
} | ||
return _.cloneDeep(array); | ||
}, | ||
@@ -243,3 +383,3 @@ getAt: function (arr, idx) { | ||
_solImmutableJs = { | ||
var _solImmutableJs = { | ||
init: function () { | ||
@@ -269,4 +409,7 @@ return Immutable.fromJS(INITIAL_OBJECT); | ||
}, | ||
initArr: function () { | ||
return Immutable.List(INITIAL_ARRAY); | ||
initArr: function (array) { | ||
if (!array) { | ||
return Immutable.List(INITIAL_ARRAY); | ||
} | ||
return Immutable.fromJS(array); | ||
}, | ||
@@ -278,6 +421,12 @@ getAt: function (arr, idx) { | ||
return arr.set(idx, val); | ||
}, | ||
getAtDeep: function (arr, idx1, idx2) { | ||
return arr.getIn([idx1, idx2]); | ||
}, | ||
setAtDeep: function (arr, idx1, idx2, val) { | ||
return arr.setIn([idx1, idx2], val); | ||
} | ||
}; | ||
_solImmutableSeamless = { | ||
var _solImmutableSeamless = { | ||
init: function () { | ||
@@ -305,4 +454,7 @@ return Seamless(INITIAL_OBJECT); | ||
}, | ||
initArr: function () { | ||
return Seamless(INITIAL_ARRAY); | ||
initArr: function (array) { | ||
if (!array) { | ||
array = INITIAL_ARRAY; | ||
} | ||
return Seamless(array); | ||
}, | ||
@@ -314,19 +466,28 @@ getAt: function (arr, idx) { | ||
return arr.set(idx, val); | ||
}, | ||
getAtDeep: function (arr, idx1, idx2) { | ||
return arr[idx1][idx2]; | ||
}, | ||
setAtDeep: function (arr, idx1, idx2, val) { | ||
return arr.setIn([idx1, idx2], val); | ||
} | ||
}; | ||
_toggle = function (solution, obj) { | ||
var _toggle = function (solution, obj) { | ||
return solution.set(obj, 'toggle', !(solution.get(obj, 'toggle'))); | ||
}; | ||
_addResult = function (results, condition) { | ||
var _addResult = function (results, condition) { | ||
return results.push(condition ? chalk.green.bold('P') : chalk.green.red('F')); | ||
}; | ||
_verify = function (solution) { | ||
var arr, arr2, get, getAt, getIn, init, initArr, merge, obj, obj2, results, set, setAt, setDeep, setIn; | ||
var _verify = function (solution) { | ||
var arr, arr2, get, getAt, getAtDeep, getIn, init, initArr, merge, obj, obj2, results, set, setAt, setDeep, setIn, setAtDeep; | ||
results = []; | ||
init = solution.init, get = solution.get, set = solution.set, setDeep = solution.setDeep, getIn = solution.getIn, setIn = solution.setIn, merge = solution.merge, initArr = solution.initArr, getAt = solution.getAt, setAt = solution.setAt; | ||
init = solution.init, get = solution.get, set = solution.set, setDeep = solution.setDeep, getIn = solution.getIn, | ||
setIn = solution.setIn, merge = solution.merge, initArr = solution.initArr, getAt = solution.getAt, setAt = solution.setAt | ||
getAtDeep = solution.getAtDeep, setAtDeep = solution.setAtDeep; | ||
obj = init(); | ||
_addResult(results, get(obj, 'toggle') === false); | ||
results.push('-'); // 1 | ||
@@ -338,2 +499,3 @@ obj2 = set(obj, 'toggle', true); | ||
_addResult(results, get(obj2, 'd') === get(obj, 'd')); | ||
results.push('-'); // 2 | ||
@@ -343,2 +505,3 @@ obj2 = set(obj, 'str', 'foo'); | ||
_addResult(results, get(obj2, 'd') === get(obj, 'd')); | ||
results.push('-'); // 3 | ||
@@ -351,2 +514,3 @@ obj2 = setDeep(obj, 'd', 'd1', 3); | ||
_addResult(results, get(obj2, 'e') === get(obj, 'e')); | ||
results.push('-'); // 4 | ||
@@ -356,2 +520,3 @@ obj2 = set(obj, 'b', get(obj, 'b')); | ||
_addResult(results, get(obj2, 'd') === get(obj, 'd')); | ||
results.push('-'); // 5 | ||
@@ -367,2 +532,3 @@ obj2 = set(obj, 'str', 'bar'); | ||
_addResult(results, get(obj2, 'd') === get(obj, 'd')); | ||
results.push('-'); // 6 | ||
@@ -375,2 +541,3 @@ obj2 = setIn(obj, DEEP_PATH, 3); | ||
_addResult(results, getIn(obj2, DEEP_PATH) === 3); | ||
results.push('-'); // 7 | ||
@@ -385,2 +552,3 @@ obj2 = merge(obj, { | ||
_addResult(results, get(obj2, 'f') === null); | ||
results.push('-'); // 8 | ||
@@ -396,6 +564,18 @@ arr = initArr(); | ||
_addResult(results, arr2 === arr); | ||
results.push('-'); // 9 | ||
arr = initArr(INITIAL_DEEP_ARRAY); | ||
arr2 = setAtDeep(arr, 3, 0, { | ||
b: 3 | ||
}); | ||
_addResult(results, arr2 !== arr); | ||
_addResult(results, get(getAtDeep(arr, 3, 0), "b") === 2); | ||
_addResult(results, getAtDeep(arr2, 3, 0).b === 3); | ||
arr2 = setAtDeep(arr, 3, 1, getAtDeep(arr, 3, 1)); | ||
_addResult(results, arr2 === arr); | ||
return console.log(" Verification: " + (results.join(''))); | ||
}; | ||
_test = function (desc, cb) { | ||
var _test = function (desc, cb) { | ||
var tac, tic; | ||
@@ -410,5 +590,5 @@ tic = new Date().getTime(); | ||
_allTests = function (desc, solution) { | ||
var _allTests = function (desc, solution) { | ||
var MERGE_OBJ, arr, obj; | ||
console.log(chalk.bold(desc)); | ||
console.log("\n" + chalk.bold(desc)); | ||
_verify(solution); | ||
@@ -485,4 +665,19 @@ obj = solution.init(); | ||
arr = solution.initArr(INITIAL_DEEP_ARRAY); | ||
totalRead += _test("Array: deep read (x" + R + ")", function () { | ||
var j, ref1, val; | ||
for (n = j = 0, ref1 = R; 0 <= ref1 ? j < ref1 : j > ref1; n = 0 <= ref1 ? ++j : --j) { | ||
val = solution.getAtDeep(arr, 3, 0); | ||
} | ||
}); | ||
arr = solution.initArr(INITIAL_DEEP_ARRAY); | ||
totalWrite += _test("Array: deep write (x" + W + ")", function () { | ||
var arr2, j, ref1; | ||
for (n = j = 0, ref1 = W; 0 <= ref1 ? j < ref1 : j > ref1; n = 0 <= ref1 ? ++j : --j) { | ||
arr2 = solution.setAtDeep(arr, 3, 0, n); | ||
} | ||
}); | ||
var totalElapsed = totalRead + totalWrite; | ||
console.log("Total elapsed = " + totalElapsed + " ms = " + totalRead + " (read) + " + totalWrite + " (write)."); | ||
console.log("Total elapsed = " + totalElapsed + " ms = " + totalRead + " ms (read) + " + totalWrite + " ms (write)."); | ||
return totalElapsed; | ||
@@ -492,11 +687,13 @@ }; | ||
_allTests("Mutable", _solMutable); | ||
_allTests("Immutable (Object.assign)", _solObjectAssign); | ||
_allTests("Immutable (immutable-assign)", _solIassign); | ||
_allTests("Immutable (immutable.js)", _solImmutableJs); | ||
// _allTests("Immutable (timm)", _solImmutableTimm); | ||
_allTests("Immutable (seamless-immutable)", _solImmutableSeamless); | ||
_allTests("Immutable (iassign)", _solIassign); | ||
// Deep freeze initial object/array | ||
_isDevel = true; | ||
_allTests("Immutable (Object.assign) + deep freeze", _solObjectAssign); | ||
_allTests("Immutable (immutable-assign) + deep freeze", _solIassign); | ||
_allTests("Immutable (ImmutableJS)", _solImmutableJs); | ||
_allTests("Immutable (timm)", _solImmutableTimm); | ||
_allTests("Immutable (seamless-immutable)", _solImmutableSeamless); | ||
}).call(this); |
// | ||
// No optimization | ||
// | ||
> immutable-assign@1.0.22 benchmarks E:\Git\Misc\ImmutableAssign | ||
@@ -3,0 +7,0 @@ > node debug/benchmarks |
// | ||
// Optimization 1: cache getProp() | ||
// | ||
> immutable-assign@1.0.22 benchmarks E:\Git\Misc\ImmutableAssign | ||
@@ -3,0 +7,0 @@ > node debug/benchmarks |
// | ||
// Optimization 2: cache post process propName | ||
// | ||
> immutable-assign@1.0.23 benchmarks E:\Git\Misc\ImmutableAssign | ||
@@ -3,0 +7,0 @@ > node debug/benchmarks |
// | ||
// Update benchmarks.js: change read/write ratio in benchmarks.js to 5/1 | ||
// | ||
> immutable-assign@1.0.23 benchmarks E:\Git\Misc\ImmutableAssign | ||
@@ -3,0 +7,0 @@ > node debug/benchmarks |
{ | ||
"name": "immutable-assign", | ||
"version": "1.0.23", | ||
"version": "1.0.24", | ||
"description": "Lightweight immutable helper that allows you to continue working with Plain JavaScript Objects", | ||
@@ -5,0 +5,0 @@ "main": "src/iassign.js", |
@@ -28,6 +28,14 @@ # immutable-assign (iassign.js) | ||
Performance of this library should be comparable to [Immutable.js](https://facebook.github.io/immutable-js/), because read operations will always occur more than write operations. When using this library, all your react components can read object properties directly. E.g., you can use <TextBox value={this.state.userinfo.fullName} /> in your components, instead of <TextBox value={this.state.getIn(["userinfo", "fullName"])} />. In addition, shouldComponentUpdate() can compare POJO objects without knowing about the immutable libraries, e.g., return this.props.userInfo.orders !== nextProps.userInfos.orders. I.e., the more read operations you have, the more it will outperform [Immutable.js](https://facebook.github.io/immutable-js/). Following are the benchmarks for mutlple immutable libraries (assuming the read to write ratio is 5 to 1): | ||
Performance of this library should be comparable to [Immutable.js](https://facebook.github.io/immutable-js/), because read operations will always occur more than write operations. When using this library, all your react components can read object properties directly. E.g., you can use <TextBox value={this.state.userinfo.fullName} /> in your components, instead of <TextBox value={this.state.getIn(["userinfo", "fullName"])} />. In addition, shouldComponentUpdate() can compare POJO objects without knowing about the immutable libraries, e.g., return this.props.userInfo.orders !== nextProps.userInfos.orders. I.e., the more read operations you have, the more it will outperform [Immutable.js](https://facebook.github.io/immutable-js/). Following are the benchmarks for multiple immutable libraries (assuming the read to write ratio is 5 to 1): | ||
![benchmarks](benchmarks.png?raw=true "benchmarks") | ||
``` | ||
npm run benchmarks | ||
``` | ||
<p> | ||
<a href="benchmarks.png?raw=true" target="_blank"> | ||
<img src="benchmarks.png?raw=true" alt="benchmarks" title="benchmarks" width="70%;"> | ||
</a> | ||
</p> | ||
##Install with npm | ||
@@ -34,0 +42,0 @@ |
Sorry, the diff of this file is not supported yet
941144
35
25072
380