| 254 | }, |
| 255 | |
| 256 | isEqual: function( to ) { |
| 257 | return this._eq( this._value, to, [], [] ); |
| 258 | }, |
| 259 | |
| 260 | /** |
| 261 | * Internal recursive comparison function for `isEqual`. |
| 262 | * Copy from Underscore.js. |
| 263 | */ |
| 264 | _eq: function(a, b, aStack, bStack) { |
| 265 | if (a === b) return a !== 0 || 1 / a == 1 / b; |
| 266 | if (a == null || b == null) return a === b; |
| 267 | |
| 268 | var className = toString.call(a); |
| 269 | if (className != toString.call(b)) return false; |
| 270 | switch (className) { |
| 271 | case '[object String]': |
| 272 | return a == String(b); |
| 273 | case '[object Number]': |
| 274 | return a != +a ? b != +b : (a == 0 ? 1 / a == 1 / b : a == +b); |
| 275 | case '[object Date]': |
| 276 | case '[object Boolean]': |
| 277 | return +a == +b; |
| 278 | case '[object RegExp]': |
| 279 | return a.source == b.source && |
| 280 | a.global == b.global && |
| 281 | a.multiline == b.multiline && |
| 282 | a.ignoreCase == b.ignoreCase; |
| 283 | } |
| 284 | if (typeof a != 'object' || typeof b != 'object') return false; |
| 285 | var length = aStack.length; |
| 286 | while (length--) { |
| 287 | if (aStack[length] == a) return bStack[length] == b; |
| 288 | } |
| 289 | var aCtor = a.constructor, bCtor = b.constructor; |
| 290 | if (aCtor !== bCtor && !((typeof aCtor === 'function') && (aCtor instanceof aCtor) && |
| 291 | (typeof bCtor === 'function') && (bCtor instanceof bCtor))) { |
| 292 | return false; |
| 293 | } |
| 294 | aStack.push(a); |
| 295 | bStack.push(b); |
| 296 | var size = 0, result = true; |
| 297 | |
| 298 | if (className == '[object Array]') { |
| 299 | size = a.length; |
| 300 | result = size == b.length; |
| 301 | if (result) { |
| 302 | while (size--) { |
| 303 | if (!(result = this._eq(a[size], b[size], aStack, bStack))) break; |
| 304 | } |
| 305 | } |
| 306 | } else { |
| 307 | for (var key in a) { |
| 308 | if (hasOwnProperty.call(a, key)) { |
| 309 | size++; |
| 310 | if (!(result = hasOwnProperty.call(b, key) && this._eq(a[key], b[key], aStack, bStack))) break; |
| 311 | } |
| 312 | } |
| 313 | if (result) { |
| 314 | for (key in b) { |
| 315 | if (hasOwnProperty.call(b, key) && !(size--)) break; |
| 316 | } |
| 317 | result = !size; |
| 318 | } |
| 319 | } |
| 320 | aStack.pop(); |
| 321 | bStack.pop(); |
| 322 | return result; |