You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							116 lines
						
					
					
						
							3.3 KiB
						
					
					
				
			
		
		
		
			
			
			
				
					
				
				
					
				
			
		
		
	
	
							116 lines
						
					
					
						
							3.3 KiB
						
					
					
				| 
 | |
| function deepCompare(x, y) { | |
|     var i, l, leftChain, rightChain; | |
| 
 | |
|     function compare2Objects(x, y) { | |
|         var p; | |
| 
 | |
|         // remember that NaN === NaN returns false | |
|         // and isNaN(undefined) returns true | |
|         if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') { | |
|             return true; | |
|         } | |
| 
 | |
|         // Compare primitives and functions.      | |
|         // Check if both arguments link to the same object. | |
|         // Especially useful on the step where we compare prototypes | |
|         if (x === y) { | |
|             return true; | |
|         } | |
| 
 | |
|         // Works in case when functions are created in constructor. | |
|         // Comparing dates is a common scenario. Another built-ins? | |
|         // We can even handle functions passed across iframes | |
|         if ((typeof x === 'function' && typeof y === 'function') || | |
|             (x instanceof Date && y instanceof Date) || | |
|             (x instanceof RegExp && y instanceof RegExp) || | |
|             (x instanceof String && y instanceof String) || | |
|             (x instanceof Number && y instanceof Number)) { | |
|             return x.toString() === y.toString(); | |
|         } | |
| 
 | |
|         // At last checking prototypes as good as we can | |
|         if (!(x instanceof Object && y instanceof Object)) { | |
|             return false; | |
|         } | |
| 
 | |
|         if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) { | |
|             return false; | |
|         } | |
| 
 | |
|         if (x.constructor !== y.constructor) { | |
|             return false; | |
|         } | |
| 
 | |
|         if (x.prototype !== y.prototype) { | |
|             return false; | |
|         } | |
| 
 | |
|         // Check for infinitive linking loops | |
|         if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) { | |
|             return false; | |
|         } | |
| 
 | |
|         // Quick checking of one object being a subset of another. | |
|         // todo: cache the structure of arguments[0] for performance | |
|         for (p in y) { | |
|             if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) { | |
|                 return false; | |
|             } else if (typeof y[p] !== typeof x[p]) { | |
|                 return false; | |
|             } | |
|         } | |
| 
 | |
|         for (p in x) { | |
|             if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) { | |
|                 return false; | |
|             } else if (typeof y[p] !== typeof x[p]) { | |
|                 return false; | |
|             } | |
| 
 | |
|             switch (typeof (x[p])) { | |
|                 case 'object': | |
|                 case 'function': | |
| 
 | |
|                     leftChain.push(x); | |
|                     rightChain.push(y); | |
| 
 | |
|                     if (!compare2Objects(x[p], y[p])) { | |
|                         return false; | |
|                     } | |
| 
 | |
|                     leftChain.pop(); | |
|                     rightChain.pop(); | |
|                     break; | |
| 
 | |
|                 default: | |
|                     if (x[p] !== y[p]) { | |
|                         return false; | |
|                     } | |
|                     break; | |
|             } | |
|         } | |
| 
 | |
|         return true; | |
|     } | |
| 
 | |
|     if (arguments.length < 1) { | |
|         return true; //Die silently? Don't know how to handle such case, please help... | |
|         // throw "Need two or more arguments to compare"; | |
|     } | |
| 
 | |
|     for (i = 1, l = arguments.length; i < l; i++) { | |
| 
 | |
|         leftChain = []; //Todo: this can be cached | |
|         rightChain = []; | |
| 
 | |
|         if (!compare2Objects(arguments[0], arguments[i])) { | |
|             return false; | |
|         } | |
|     } | |
| 
 | |
|     return true; | |
| } | |
| module.exports = { | |
|     deepCompare | |
| } |