11/** Deep Copy
22 * Return a copy of the object passed as param, doing (recursivelly) copys of
33 * all the objects the initial has.
4- *
4+ *
55 * Caution!!!
66 * This function is recursive. Copying a very deep object might concern heavy
77 * performance issues. Use your brain before the function.
8+ *
9+ * @param oldObj {Object} Object to clone
810 */
911function deepCopy ( oldObj ) {
10- var newObj = oldObj ;
11- if ( oldObj && typeof oldObj === 'object' ) {
12- newObj = Object . prototype . toString . call ( oldObj ) === '[object Array]' ? [ ] : { } ;
13- for ( var i in oldObj ) {
14- newObj [ i ] = deepCopy ( oldObj [ i ] ) ;
15- }
16- }
17- return newObj ;
12+ var newObj = oldObj ;
13+ if ( oldObj && typeof oldObj === 'object' ) {
14+ newObj = Object . prototype . toString . call ( oldObj ) === '[object Array]' ? [ ] : { } ;
15+ for ( var i in oldObj ) {
16+ newObj [ i ] = deepCopy ( oldObj [ i ] ) ;
17+ }
18+ }
19+ return newObj ;
1820}
1921
2022/** Merge
@@ -24,28 +26,110 @@ function deepCopy(oldObj) {
2426 * A third parameter, avoidDeepCopy is also included to avoid creating a deep
2527 * copy of the objects. With this parameter to true, original objects may get
2628 * updated, linked or similar unexpected behaviour.
29+ *
30+ * @param old {Object} Object to use as base
31+ * @param obj {Object} Object to get data from
32+ * @param avoidDeepCopy {booleam} Seting to true will update the "old" object
2733 */
2834function merge ( old , obj , avoidDeepCopy ) {
29-
30- let dest , orig ;
31-
32- if ( avoidDeepCopy ) {
33- dest = old ;
34- orig = obj ;
35- } else {
36- dest = deepCopy ( old ) ;
37- orig = deepCopy ( obj ) ;
38- }
39-
40- for ( let prop in orig ) {
41- dest [ prop ] = orig [ prop ] ;
42- }
43-
44- return dest ;
35+ let dest , orig ;
36+
37+ if ( avoidDeepCopy ) {
38+ dest = old ;
39+ orig = obj ;
40+ } else {
41+ dest = deepCopy ( old ) ;
42+ orig = deepCopy ( obj ) ;
43+ }
44+
45+ for ( let prop in orig ) {
46+ dest [ prop ] = orig [ prop ] ;
47+ }
48+
49+ return dest ;
4550}
4651
52+ /** Equal
53+ * Check if two objects are equal.
54+ *
55+ * Seen in:
56+ * https://github.com/epoberezkin/fast-deep-equal/
57+ *
58+ * @param a {Object} First object
59+ * @param b {Object} Seccond object
60+ */
61+ function equal ( a , b ) {
62+ if ( a === b ) {
63+ return true ;
64+ }
65+
66+ var arrA = Array . isArray ( a ) ;
67+ var arrB = Array . isArray ( b ) ;
68+ var i ;
69+
70+ if ( arrA && arrB ) {
71+ if ( a . length !== b . length ) {
72+ return false ;
73+ }
74+
75+ for ( i = 0 ; i < a . length ; i ++ ) {
76+ if ( ! equal ( a [ i ] , b [ i ] ) ) {
77+ return false ;
78+ }
79+ }
80+
81+ return true ;
82+ }
83+
84+ if ( arrA !== arrB ) {
85+ return false ;
86+ }
87+
88+ if ( a && b && typeof a === 'object' && typeof b === 'object' ) {
89+ var keys = Object . keys ( a ) ;
90+ if ( keys . length !== Object . keys ( b ) . length ) {
91+ return false ;
92+ }
93+
94+ var dateA = a instanceof Date ;
95+ var dateB = b instanceof Date ;
96+ if ( dateA && dateB ) {
97+ return a . getTime ( ) === b . getTime ( ) ;
98+ }
99+
100+ if ( dateA !== dateB ) {
101+ return false ;
102+ }
103+
104+ var regexpA = a instanceof RegExp ;
105+ var regexpB = b instanceof RegExp ;
106+ if ( regexpA && regexpB ) {
107+ return a . toString ( ) === b . toString ( ) ;
108+ }
109+ if ( regexpA !== regexpB ) {
110+ return false ;
111+ }
112+
113+ for ( i = 0 ; i < keys . length ; i ++ ) {
114+ if ( ! Object . prototype . hasOwnProperty . call ( b , keys [ i ] ) ) {
115+ return false ;
116+ }
117+ }
118+
119+ for ( i = 0 ; i < keys . length ; i ++ ) {
120+ if ( ! equal ( a [ keys [ i ] ] , b [ keys [ i ] ] ) ) {
121+ return false ;
122+ }
123+ }
124+
125+ return true ;
126+ }
127+
128+ return false ;
129+ }
47130
48131module . exports = {
49132 merge : merge ,
133+ equal : equal ,
50134 clone : deepCopy
51135} ;
0 commit comments