(obj1, obj2)
| 395 | |
| 396 | // Utility for deep equality testing of objects |
| 397 | function objectsEqual (obj1, obj2) { |
| 398 | /* jshint eqeqeq: false */ |
| 399 | |
| 400 | // Check for undefined or null |
| 401 | if (isUndefinedOrNull(obj1) || isUndefinedOrNull(obj2)) { |
| 402 | return false; |
| 403 | } |
| 404 | |
| 405 | // Object prototypes must be the same |
| 406 | if (obj1.prototype !== obj2.prototype) { |
| 407 | return false; |
| 408 | } |
| 409 | |
| 410 | // Handle argument objects |
| 411 | if (isArgumentsObject(obj1)) { |
| 412 | if (!isArgumentsObject(obj2)) { |
| 413 | return false; |
| 414 | } |
| 415 | obj1 = Array.prototype.slice.call(obj1); |
| 416 | obj2 = Array.prototype.slice.call(obj2); |
| 417 | } |
| 418 | |
| 419 | // Check number of own properties |
| 420 | var obj1Keys = getObjectKeys(obj1); |
| 421 | var obj2Keys = getObjectKeys(obj2); |
| 422 | if (obj1Keys.length !== obj2Keys.length) { |
| 423 | return false; |
| 424 | } |
| 425 | |
| 426 | obj1Keys.sort(); |
| 427 | obj2Keys.sort(); |
| 428 | |
| 429 | // Cheap initial key test (see https://github.com/joyent/node/blob/master/lib/assert.js) |
| 430 | var key, i, len = obj1Keys.length; |
| 431 | for (i = 0; i < len; i += 1) { |
| 432 | if (obj1Keys[i] != obj2Keys[i]) { |
| 433 | return false; |
| 434 | } |
| 435 | } |
| 436 | |
| 437 | // Expensive deep test |
| 438 | for (i = 0; i < len; i += 1) { |
| 439 | key = obj1Keys[i]; |
| 440 | if (!isDeepEqual(obj1[key], obj2[key])) { |
| 441 | return false; |
| 442 | } |
| 443 | } |
| 444 | |
| 445 | // If it got this far... |
| 446 | return true; |
| 447 | } |
| 448 | |
| 449 | // Utility for deep equality testing |
| 450 | function isDeepEqual (actual, expected) { |
no test coverage detected