├── .gitignore
├── test
└── index-test.js
├── package.json
├── LICENSE
├── README.md
└── index.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Directory for instrumented libs generated by jscoverage/JSCover
11 | lib-cov
12 |
13 | # Coverage directory used by tools like istanbul
14 | coverage
15 |
16 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
17 | .grunt
18 |
19 | # node-waf configuration
20 | .lock-wscript
21 |
22 | # Compiled binary addons (http://nodejs.org/api/addons.html)
23 | build/Release
24 |
25 | # Dependency directory
26 | # https://www.npmjs.org/doc/misc/npm-faq.html#should-i-check-my-node_modules-folder-into-git
27 | node_modules
28 |
29 | .idea
30 |
--------------------------------------------------------------------------------
/test/index-test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const assert = require('assert');
4 | const FastClone = require('../');
5 |
6 | describe('index', function () {
7 | it('FastClone.factory', function () {
8 | const sourceArray = [
9 | {a: 1, b: [{c: "d", f: {g: 3}}]},
10 | {a: 2, b: [{c: "e", f: {g: 4}}]}
11 | ];
12 | const clonedArray = FastClone.cloneArray(sourceArray);
13 |
14 | assert.deepEqual(sourceArray[0], clonedArray[0]);
15 | assert.deepEqual(sourceArray[1], clonedArray[1]);
16 |
17 | clonedArray[0].a = 3;
18 | clonedArray[0].b[0].c = "f";
19 | clonedArray[0].b[0].f.g = 10;
20 |
21 | assert.notDeepEqual(sourceArray[0], clonedArray[0]);
22 | assert.notEqual(sourceArray[0].b[0].f.g, clonedArray[0].b[0].f.g);
23 | });
24 | });
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "fastest-clone",
3 | "version": "1.0.1",
4 | "description": "Library for fastest array cloning or copy objects with similar structures",
5 | "main": "index.js",
6 | "directories": {
7 | "test": "test"
8 | },
9 | "dependencies": {},
10 | "devDependencies": {
11 | "mocha": "^2.5.3"
12 | },
13 | "scripts": {
14 | "test": "mocha"
15 | },
16 | "repository": {
17 | "type": "git",
18 | "url": "git+https://github.com/ivolovikov/fastest-clone.git"
19 | },
20 | "keywords": [
21 | "clone",
22 | "fast clone",
23 | "fast array clone",
24 | "fast array object"
25 | ],
26 | "author": "Ivan Volovikov",
27 | "license": "MIT",
28 | "bugs": {
29 | "url": "https://github.com/ivolovikov/fastest-clone/issues"
30 | },
31 | "homepage": "https://github.com/ivolovikov/fastest-clone#readme"
32 | }
33 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Ivan Volovikov
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## Fast Array Clone Library
2 |
3 | This library can **200X times faster** than *lodash* (benchmark) make deep copies of an array or objects with similar structure in JavaScript
4 |
5 | ### EXAMPLE
6 | ```javascript
7 | // array of SAME STRUCTURED object
8 | var sourceArray = [{ f1 : ..., f2: ... }, ...];
9 | ```
10 |
11 | You can use built-in array clone function:
12 | ```javascript
13 | var clonedArray = FastClone.cloneArray(sourceArray);
14 | ```
15 | or object clone constructor factory:
16 | ```javascript
17 | // creating deep clone constructor function
18 | var Clone = FastClone.factory(sourceArray[0]);
19 | var clonedArray = sourceArray.map(function(item) {
20 | // you can add here custom logic
21 | return new Clone(item);
22 | });
23 | ```
24 | ### INSTALLATION
25 | In a browser:
26 | ```html
27 |
28 | ```
29 | Using npm:
30 | ```
31 | npm install fastest-clone
32 | ```
33 | ### BENCHMARK
34 | Result for Chromium 50.0.2661.102 Ubuntu 14.04 (64-bit)
35 |
36 | Library | Ops/sec
37 | ------------ | -------------
38 | lodash | 66,313
39 | JQuery | 62,164
40 | **FastClone** | **16,927,673**
41 | Benchmark source code - benchmark
42 |
43 |
44 | ### LICENSE
45 |
46 | Copyright (c) 2016 Ivan Volovikov
47 |
48 | Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
49 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * FastClone JavaScript Library v1.0.0
3 | *
4 | * This library perform very fast cloning
5 | * of objects WITH THE SAME STRUCTURE
6 | *
7 | * @example
8 | * var sourceArray = [{ f1 : ..., f2: ... }, ...]; // array of SAME STRUCTURED object
9 | *
10 | * // you can use built-in function for clone array
11 | * var clonedArray = FastClone.cloneArray(sourceArray);
12 | *
13 | * // or write a custom code with clone constructor factory
14 | * var Clone = FastClone.factory(sourceArray[0]); // creating deep clone constructor function
15 | * var clonedArray = sourceArray.map(function(item) {
16 | * return new Clone(item);
17 | * });
18 | *
19 | * Copyright 2015 Ivan Volovikov
20 | * Released under the MIT license
21 | * https://github.com/ivolovikov/fastest-clone
22 | */
23 | var FastClone = {
24 |
25 | /**
26 | * This is a factory method that creates clone constructor function
27 | * for a specified object
28 | *
29 | * @param {Object} source - source object that need to be cloned next
30 | * @param {Boolean} isDeep - flag that represents should be clone deep or not (default: true)
31 | * @returns {Function}
32 | */
33 | factory: function (source, isDeep) {
34 | if (typeof source != 'object' || Array.isArray(source)) {
35 | throw new Error('Source is not an object');
36 | }
37 | var deep = isDeep === undefined ? true : isDeep;
38 |
39 | return new Function('src', FastClone._getKeyMap(source, deep));
40 | },
41 |
42 | /**
43 | * This method is for array cloning
44 | *
45 | * @param {Array} source - source array to clone
46 | * @param {Boolean} isDeep - flag that represents should be clone deep or not (default: true)
47 | * @returns {Array}
48 | */
49 | cloneArray: function(source, isDeep) {
50 | if (!Array.isArray(source)) {
51 | throw new Error('Source should be an array');
52 | }
53 | var deep = isDeep === undefined ? true : isDeep;
54 |
55 | var clonedArray = [];
56 | if (source.length) {
57 | var Clone = FastClone.factory(source[0], deep);
58 | for (var i = 0; i < source.length; i++) {
59 | clonedArray.push(new Clone(source[i]));
60 | }
61 | }
62 | return clonedArray;
63 | },
64 |
65 | /**
66 | * This method create map of object fields
67 | * for eval in clone function
68 | *
69 | * @param {Object|Array} source - source object that need to be cloned next
70 | * @param {Boolean} deep - flag that represents should be clone deep or not
71 | * @param {String} baseKey - current sequence of object keys
72 | * @param {Number} arrIndex - current sequence of array indexes
73 | * @returns {string}
74 | */
75 | _getKeyMap: function (source, deep, baseKey, arrIndex) {
76 | var base = baseKey || '';
77 | var index = (arrIndex || 0) + 1;
78 |
79 | var keysMap = base ? 'this' + base : '';
80 |
81 | if (Array.isArray(source)) {
82 | var iterVal = 'i' + index; // name of the current counter value
83 | var iterPath = base + '[' + iterVal + ']'; // path of the current array value
84 |
85 | if (typeof source[0] == 'object') {
86 | // This cycle will write code for copy array values
87 | keysMap += base ? ' = [];' : '';
88 | keysMap += 'for (var ' + iterVal + ' = 0; ' + iterVal + ' < src' + base + '.length; ' + iterVal + '++) {';
89 | keysMap += FastClone._getKeyMap(source[0], deep, iterPath, index);
90 | keysMap += '}';
91 | } else {
92 | keysMap += ' = src' + base + '.slice();';
93 | }
94 | } else {
95 | keysMap += base ? ' = {};' : '';
96 |
97 | // Iterate over object keys
98 | for (var key in source) {
99 | if (!source.hasOwnProperty(key)) {
100 | continue;
101 | }
102 |
103 | var value = source[key];
104 | var path = base + '.' + key; // current key path
105 |
106 | if (deep && typeof value == 'object' && value !== null) {
107 | keysMap += FastClone._getKeyMap(value, deep, path, index);
108 | } else {
109 | keysMap += 'this' + path + ' = src' + path + ';';
110 | }
111 | }
112 | }
113 |
114 | return keysMap;
115 | }
116 | };
117 |
118 | if (typeof module == 'object' && typeof module.exports == 'object') {
119 | module.exports = FastClone;
120 | }
121 |
--------------------------------------------------------------------------------