Files
web-apps/vendor/underscore/docs/modules/isEqual.html
2024-03-06 21:54:19 +05:00

1421 lines
50 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<title>isEqual.js</title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, target-densitydpi=160dpi, initial-scale=1.0; maximum-scale=1.0; user-scalable=0;">
<link rel="stylesheet" media="all" href="../docco.css" />
</head>
<body>
<div id="container">
<div id="background"></div>
<ul id="jump_to">
<li>
<a class="large" href="javascript:void(0);">Jump To &hellip;</a>
<a class="small" href="javascript:void(0);">+</a>
<div id="jump_wrapper">
<div id="jump_page_wrapper">
<div id="jump_page">
<a class="source" href="_baseCreate.html">
modules/_baseCreate.js
</a>
<a class="source" href="_baseIteratee.html">
modules/_baseIteratee.js
</a>
<a class="source" href="_cb.html">
modules/_cb.js
</a>
<a class="source" href="_chainResult.html">
modules/_chainResult.js
</a>
<a class="source" href="_collectNonEnumProps.html">
modules/_collectNonEnumProps.js
</a>
<a class="source" href="_createAssigner.html">
modules/_createAssigner.js
</a>
<a class="source" href="_createEscaper.html">
modules/_createEscaper.js
</a>
<a class="source" href="_createIndexFinder.html">
modules/_createIndexFinder.js
</a>
<a class="source" href="_createPredicateIndexFinder.html">
modules/_createPredicateIndexFinder.js
</a>
<a class="source" href="_createReduce.html">
modules/_createReduce.js
</a>
<a class="source" href="_createSizePropertyCheck.html">
modules/_createSizePropertyCheck.js
</a>
<a class="source" href="_deepGet.html">
modules/_deepGet.js
</a>
<a class="source" href="_escapeMap.html">
modules/_escapeMap.js
</a>
<a class="source" href="_executeBound.html">
modules/_executeBound.js
</a>
<a class="source" href="_flatten.html">
modules/_flatten.js
</a>
<a class="source" href="_getByteLength.html">
modules/_getByteLength.js
</a>
<a class="source" href="_getLength.html">
modules/_getLength.js
</a>
<a class="source" href="_group.html">
modules/_group.js
</a>
<a class="source" href="_has.html">
modules/_has.js
</a>
<a class="source" href="_hasObjectTag.html">
modules/_hasObjectTag.js
</a>
<a class="source" href="_isArrayLike.html">
modules/_isArrayLike.js
</a>
<a class="source" href="_isBufferLike.html">
modules/_isBufferLike.js
</a>
<a class="source" href="_keyInObj.html">
modules/_keyInObj.js
</a>
<a class="source" href="_methodFingerprint.html">
modules/_methodFingerprint.js
</a>
<a class="source" href="_optimizeCb.html">
modules/_optimizeCb.js
</a>
<a class="source" href="_setup.html">
modules/_setup.js
</a>
<a class="source" href="_shallowProperty.html">
modules/_shallowProperty.js
</a>
<a class="source" href="_stringTagBug.html">
modules/_stringTagBug.js
</a>
<a class="source" href="_tagTester.html">
modules/_tagTester.js
</a>
<a class="source" href="_toBufferView.html">
modules/_toBufferView.js
</a>
<a class="source" href="_toPath.html">
modules/_toPath.js
</a>
<a class="source" href="_unescapeMap.html">
modules/_unescapeMap.js
</a>
<a class="source" href="after.html">
modules/after.js
</a>
<a class="source" href="allKeys.html">
modules/allKeys.js
</a>
<a class="source" href="before.html">
modules/before.js
</a>
<a class="source" href="bind.html">
modules/bind.js
</a>
<a class="source" href="bindAll.html">
modules/bindAll.js
</a>
<a class="source" href="chain.html">
modules/chain.js
</a>
<a class="source" href="chunk.html">
modules/chunk.js
</a>
<a class="source" href="clone.html">
modules/clone.js
</a>
<a class="source" href="compact.html">
modules/compact.js
</a>
<a class="source" href="compose.html">
modules/compose.js
</a>
<a class="source" href="constant.html">
modules/constant.js
</a>
<a class="source" href="contains.html">
modules/contains.js
</a>
<a class="source" href="countBy.html">
modules/countBy.js
</a>
<a class="source" href="create.html">
modules/create.js
</a>
<a class="source" href="debounce.html">
modules/debounce.js
</a>
<a class="source" href="defaults.html">
modules/defaults.js
</a>
<a class="source" href="defer.html">
modules/defer.js
</a>
<a class="source" href="delay.html">
modules/delay.js
</a>
<a class="source" href="difference.html">
modules/difference.js
</a>
<a class="source" href="each.html">
modules/each.js
</a>
<a class="source" href="escape.html">
modules/escape.js
</a>
<a class="source" href="every.html">
modules/every.js
</a>
<a class="source" href="extend.html">
modules/extend.js
</a>
<a class="source" href="extendOwn.html">
modules/extendOwn.js
</a>
<a class="source" href="filter.html">
modules/filter.js
</a>
<a class="source" href="find.html">
modules/find.js
</a>
<a class="source" href="findIndex.html">
modules/findIndex.js
</a>
<a class="source" href="findKey.html">
modules/findKey.js
</a>
<a class="source" href="findLastIndex.html">
modules/findLastIndex.js
</a>
<a class="source" href="findWhere.html">
modules/findWhere.js
</a>
<a class="source" href="first.html">
modules/first.js
</a>
<a class="source" href="flatten.html">
modules/flatten.js
</a>
<a class="source" href="functions.html">
modules/functions.js
</a>
<a class="source" href="get.html">
modules/get.js
</a>
<a class="source" href="groupBy.html">
modules/groupBy.js
</a>
<a class="source" href="has.html">
modules/has.js
</a>
<a class="source" href="identity.html">
modules/identity.js
</a>
<a class="source" href="index-all.html">
modules/index-all.js
</a>
<a class="source" href="index-default.html">
modules/index-default.js
</a>
<a class="source" href="index.html">
modules/index.js
</a>
<a class="source" href="indexBy.html">
modules/indexBy.js
</a>
<a class="source" href="indexOf.html">
modules/indexOf.js
</a>
<a class="source" href="initial.html">
modules/initial.js
</a>
<a class="source" href="intersection.html">
modules/intersection.js
</a>
<a class="source" href="invert.html">
modules/invert.js
</a>
<a class="source" href="invoke.html">
modules/invoke.js
</a>
<a class="source" href="isArguments.html">
modules/isArguments.js
</a>
<a class="source" href="isArray.html">
modules/isArray.js
</a>
<a class="source" href="isArrayBuffer.html">
modules/isArrayBuffer.js
</a>
<a class="source" href="isBoolean.html">
modules/isBoolean.js
</a>
<a class="source" href="isDataView.html">
modules/isDataView.js
</a>
<a class="source" href="isDate.html">
modules/isDate.js
</a>
<a class="source" href="isElement.html">
modules/isElement.js
</a>
<a class="source" href="isEmpty.html">
modules/isEmpty.js
</a>
<a class="source" href="isEqual.html">
modules/isEqual.js
</a>
<a class="source" href="isError.html">
modules/isError.js
</a>
<a class="source" href="isFinite.html">
modules/isFinite.js
</a>
<a class="source" href="isFunction.html">
modules/isFunction.js
</a>
<a class="source" href="isMap.html">
modules/isMap.js
</a>
<a class="source" href="isMatch.html">
modules/isMatch.js
</a>
<a class="source" href="isNaN.html">
modules/isNaN.js
</a>
<a class="source" href="isNull.html">
modules/isNull.js
</a>
<a class="source" href="isNumber.html">
modules/isNumber.js
</a>
<a class="source" href="isObject.html">
modules/isObject.js
</a>
<a class="source" href="isRegExp.html">
modules/isRegExp.js
</a>
<a class="source" href="isSet.html">
modules/isSet.js
</a>
<a class="source" href="isString.html">
modules/isString.js
</a>
<a class="source" href="isSymbol.html">
modules/isSymbol.js
</a>
<a class="source" href="isTypedArray.html">
modules/isTypedArray.js
</a>
<a class="source" href="isUndefined.html">
modules/isUndefined.js
</a>
<a class="source" href="isWeakMap.html">
modules/isWeakMap.js
</a>
<a class="source" href="isWeakSet.html">
modules/isWeakSet.js
</a>
<a class="source" href="iteratee.html">
modules/iteratee.js
</a>
<a class="source" href="keys.html">
modules/keys.js
</a>
<a class="source" href="last.html">
modules/last.js
</a>
<a class="source" href="lastIndexOf.html">
modules/lastIndexOf.js
</a>
<a class="source" href="map.html">
modules/map.js
</a>
<a class="source" href="mapObject.html">
modules/mapObject.js
</a>
<a class="source" href="matcher.html">
modules/matcher.js
</a>
<a class="source" href="max.html">
modules/max.js
</a>
<a class="source" href="memoize.html">
modules/memoize.js
</a>
<a class="source" href="min.html">
modules/min.js
</a>
<a class="source" href="mixin.html">
modules/mixin.js
</a>
<a class="source" href="negate.html">
modules/negate.js
</a>
<a class="source" href="noop.html">
modules/noop.js
</a>
<a class="source" href="now.html">
modules/now.js
</a>
<a class="source" href="object.html">
modules/object.js
</a>
<a class="source" href="omit.html">
modules/omit.js
</a>
<a class="source" href="once.html">
modules/once.js
</a>
<a class="source" href="pairs.html">
modules/pairs.js
</a>
<a class="source" href="partial.html">
modules/partial.js
</a>
<a class="source" href="partition.html">
modules/partition.js
</a>
<a class="source" href="pick.html">
modules/pick.js
</a>
<a class="source" href="pluck.html">
modules/pluck.js
</a>
<a class="source" href="property.html">
modules/property.js
</a>
<a class="source" href="propertyOf.html">
modules/propertyOf.js
</a>
<a class="source" href="random.html">
modules/random.js
</a>
<a class="source" href="range.html">
modules/range.js
</a>
<a class="source" href="reduce.html">
modules/reduce.js
</a>
<a class="source" href="reduceRight.html">
modules/reduceRight.js
</a>
<a class="source" href="reject.html">
modules/reject.js
</a>
<a class="source" href="rest.html">
modules/rest.js
</a>
<a class="source" href="restArguments.html">
modules/restArguments.js
</a>
<a class="source" href="result.html">
modules/result.js
</a>
<a class="source" href="sample.html">
modules/sample.js
</a>
<a class="source" href="shuffle.html">
modules/shuffle.js
</a>
<a class="source" href="size.html">
modules/size.js
</a>
<a class="source" href="some.html">
modules/some.js
</a>
<a class="source" href="sortBy.html">
modules/sortBy.js
</a>
<a class="source" href="sortedIndex.html">
modules/sortedIndex.js
</a>
<a class="source" href="tap.html">
modules/tap.js
</a>
<a class="source" href="template.html">
modules/template.js
</a>
<a class="source" href="templateSettings.html">
modules/templateSettings.js
</a>
<a class="source" href="throttle.html">
modules/throttle.js
</a>
<a class="source" href="times.html">
modules/times.js
</a>
<a class="source" href="toArray.html">
modules/toArray.js
</a>
<a class="source" href="toPath.html">
modules/toPath.js
</a>
<a class="source" href="underscore-array-methods.html">
modules/underscore-array-methods.js
</a>
<a class="source" href="underscore.html">
modules/underscore.js
</a>
<a class="source" href="unescape.html">
modules/unescape.js
</a>
<a class="source" href="union.html">
modules/union.js
</a>
<a class="source" href="uniq.html">
modules/uniq.js
</a>
<a class="source" href="uniqueId.html">
modules/uniqueId.js
</a>
<a class="source" href="unzip.html">
modules/unzip.js
</a>
<a class="source" href="values.html">
modules/values.js
</a>
<a class="source" href="where.html">
modules/where.js
</a>
<a class="source" href="without.html">
modules/without.js
</a>
<a class="source" href="wrap.html">
modules/wrap.js
</a>
<a class="source" href="zip.html">
modules/zip.js
</a>
</div>
</div>
</li>
</ul>
<ul class="sections">
<li id="title">
<div class="annotation">
<h1>isEqual.js</h1>
</div>
</li>
<li id="section-1">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-1">&#182;</a>
</div>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">import</span> _ <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./underscore.js&#x27;</span>;
<span class="hljs-keyword">import</span> { toString, <span class="hljs-title class_">SymbolProto</span> } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./_setup.js&#x27;</span>;
<span class="hljs-keyword">import</span> getByteLength <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./_getByteLength.js&#x27;</span>;
<span class="hljs-keyword">import</span> isTypedArray <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./isTypedArray.js&#x27;</span>;
<span class="hljs-keyword">import</span> isFunction <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./isFunction.js&#x27;</span>;
<span class="hljs-keyword">import</span> { hasStringTagBug } <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./_stringTagBug.js&#x27;</span>;
<span class="hljs-keyword">import</span> isDataView <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./isDataView.js&#x27;</span>;
<span class="hljs-keyword">import</span> keys <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./keys.js&#x27;</span>;
<span class="hljs-keyword">import</span> has <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./_has.js&#x27;</span>;
<span class="hljs-keyword">import</span> toBufferView <span class="hljs-keyword">from</span> <span class="hljs-string">&#x27;./_toBufferView.js&#x27;</span>;</pre></div></div>
</li>
<li id="section-2">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-2">&#182;</a>
</div>
<p>We use this string twice, so give it a name for minification.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">var</span> tagDataView = <span class="hljs-string">&#x27;[object DataView]&#x27;</span>;</pre></div></div>
</li>
<li id="section-3">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-3">&#182;</a>
</div>
<p>Internal recursive comparison function for <code>_.isEqual</code>.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">function</span> <span class="hljs-title function_">eq</span>(<span class="hljs-params">a, b, aStack, bStack</span>) {</pre></div></div>
</li>
<li id="section-4">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-4">&#182;</a>
</div>
<p>Identical objects are equal. <code>0 === -0</code>, but they arent identical.
See the <a href="https://wiki.ecmascript.org/doku.php?id=harmony:egal">Harmony <code>egal</code> proposal</a>.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (a === b) <span class="hljs-keyword">return</span> a !== <span class="hljs-number">0</span> || <span class="hljs-number">1</span> / a === <span class="hljs-number">1</span> / b;</pre></div></div>
</li>
<li id="section-5">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-5">&#182;</a>
</div>
<p><code>null</code> or <code>undefined</code> only equal to itself (strict comparison).</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (a == <span class="hljs-literal">null</span> || b == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</pre></div></div>
</li>
<li id="section-6">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-6">&#182;</a>
</div>
<p><code>NaN</code>s are equivalent, but non-reflexive.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (a !== a) <span class="hljs-keyword">return</span> b !== b;</pre></div></div>
</li>
<li id="section-7">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-7">&#182;</a>
</div>
<p>Exhaust primitive checks</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> type = <span class="hljs-keyword">typeof</span> a;
<span class="hljs-keyword">if</span> (type !== <span class="hljs-string">&#x27;function&#x27;</span> &amp;&amp; type !== <span class="hljs-string">&#x27;object&#x27;</span> &amp;&amp; <span class="hljs-keyword">typeof</span> b != <span class="hljs-string">&#x27;object&#x27;</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
<span class="hljs-keyword">return</span> <span class="hljs-title function_">deepEq</span>(a, b, aStack, bStack);
}</pre></div></div>
</li>
<li id="section-8">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-8">&#182;</a>
</div>
<p>Internal recursive comparison function for <code>_.isEqual</code>.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">function</span> <span class="hljs-title function_">deepEq</span>(<span class="hljs-params">a, b, aStack, bStack</span>) {</pre></div></div>
</li>
<li id="section-9">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-9">&#182;</a>
</div>
<p>Unwrap any wrapped objects.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (a <span class="hljs-keyword">instanceof</span> _) a = a.<span class="hljs-property">_wrapped</span>;
<span class="hljs-keyword">if</span> (b <span class="hljs-keyword">instanceof</span> _) b = b.<span class="hljs-property">_wrapped</span>;</pre></div></div>
</li>
<li id="section-10">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-10">&#182;</a>
</div>
<p>Compare <code>[[Class]]</code> names.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> className = toString.<span class="hljs-title function_">call</span>(a);
<span class="hljs-keyword">if</span> (className !== toString.<span class="hljs-title function_">call</span>(b)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</pre></div></div>
</li>
<li id="section-11">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-11">&#182;</a>
</div>
<p>Work around a bug in IE 10 - Edge 13.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (hasStringTagBug &amp;&amp; className == <span class="hljs-string">&#x27;[object Object]&#x27;</span> &amp;&amp; <span class="hljs-title function_">isDataView</span>(a)) {
<span class="hljs-keyword">if</span> (!<span class="hljs-title function_">isDataView</span>(b)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
className = tagDataView;
}
<span class="hljs-keyword">switch</span> (className) {</pre></div></div>
</li>
<li id="section-12">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-12">&#182;</a>
</div>
<p>These types are compared by value.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;[object RegExp]&#x27;</span>:</pre></div></div>
</li>
<li id="section-13">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-13">&#182;</a>
</div>
<p>RegExps are coerced to strings for comparison (Note: + /a/i === /a/i)</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;[object String]&#x27;</span>:</pre></div></div>
</li>
<li id="section-14">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-14">&#182;</a>
</div>
<p>Primitives and their corresponding object wrappers are equivalent; thus, <code>&quot;5&quot;</code> is
equivalent to <code>new String(&quot;5&quot;)</code>.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-string">&#x27;&#x27;</span> + a === <span class="hljs-string">&#x27;&#x27;</span> + b;
<span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;[object Number]&#x27;</span>:</pre></div></div>
</li>
<li id="section-15">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-15">&#182;</a>
</div>
<p><code>NaN</code>s are equivalent, but non-reflexive.
Object(NaN) is equivalent to NaN.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (+a !== +a) <span class="hljs-keyword">return</span> +b !== +b;</pre></div></div>
</li>
<li id="section-16">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-16">&#182;</a>
</div>
<p>An <code>egal</code> comparison is performed for other numeric values.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> +a === <span class="hljs-number">0</span> ? <span class="hljs-number">1</span> / +a === <span class="hljs-number">1</span> / b : +a === +b;
<span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;[object Date]&#x27;</span>:
<span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;[object Boolean]&#x27;</span>:</pre></div></div>
</li>
<li id="section-17">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-17">&#182;</a>
</div>
<p>Coerce dates and booleans to numeric primitive values. Dates are compared by their
millisecond representations. Note that invalid dates with millisecond representations
of <code>NaN</code> are not equivalent.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> +a === +b;
<span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;[object Symbol]&#x27;</span>:
<span class="hljs-keyword">return</span> <span class="hljs-title class_">SymbolProto</span>.<span class="hljs-property">valueOf</span>.<span class="hljs-title function_">call</span>(a) === <span class="hljs-title class_">SymbolProto</span>.<span class="hljs-property">valueOf</span>.<span class="hljs-title function_">call</span>(b);
<span class="hljs-keyword">case</span> <span class="hljs-string">&#x27;[object ArrayBuffer]&#x27;</span>:
<span class="hljs-keyword">case</span> <span class="hljs-attr">tagDataView</span>:</pre></div></div>
</li>
<li id="section-18">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-18">&#182;</a>
</div>
<p>Coerce to typed array so we can fall through.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">return</span> <span class="hljs-title function_">deepEq</span>(<span class="hljs-title function_">toBufferView</span>(a), <span class="hljs-title function_">toBufferView</span>(b), aStack, bStack);
}
<span class="hljs-keyword">var</span> areArrays = className === <span class="hljs-string">&#x27;[object Array]&#x27;</span>;
<span class="hljs-keyword">if</span> (!areArrays &amp;&amp; <span class="hljs-title function_">isTypedArray</span>(a)) {
<span class="hljs-keyword">var</span> byteLength = <span class="hljs-title function_">getByteLength</span>(a);
<span class="hljs-keyword">if</span> (byteLength !== <span class="hljs-title function_">getByteLength</span>(b)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
<span class="hljs-keyword">if</span> (a.<span class="hljs-property">buffer</span> === b.<span class="hljs-property">buffer</span> &amp;&amp; a.<span class="hljs-property">byteOffset</span> === b.<span class="hljs-property">byteOffset</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
areArrays = <span class="hljs-literal">true</span>;
}
<span class="hljs-keyword">if</span> (!areArrays) {
<span class="hljs-keyword">if</span> (<span class="hljs-keyword">typeof</span> a != <span class="hljs-string">&#x27;object&#x27;</span> || <span class="hljs-keyword">typeof</span> b != <span class="hljs-string">&#x27;object&#x27;</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</pre></div></div>
</li>
<li id="section-19">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-19">&#182;</a>
</div>
<p>Objects with different constructors are not equivalent, but <code>Object</code>s or <code>Array</code>s
from different frames are.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> aCtor = a.<span class="hljs-property">constructor</span>, bCtor = b.<span class="hljs-property">constructor</span>;
<span class="hljs-keyword">if</span> (aCtor !== bCtor &amp;&amp; !(<span class="hljs-title function_">isFunction</span>(aCtor) &amp;&amp; aCtor <span class="hljs-keyword">instanceof</span> aCtor &amp;&amp;
<span class="hljs-title function_">isFunction</span>(bCtor) &amp;&amp; bCtor <span class="hljs-keyword">instanceof</span> bCtor)
&amp;&amp; (<span class="hljs-string">&#x27;constructor&#x27;</span> <span class="hljs-keyword">in</span> a &amp;&amp; <span class="hljs-string">&#x27;constructor&#x27;</span> <span class="hljs-keyword">in</span> b)) {
<span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
}</pre></div></div>
</li>
<li id="section-20">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-20">&#182;</a>
</div>
<p>Assume equality for cyclic structures. The algorithm for detecting cyclic
structures is adapted from ES 5.1 section 15.12.3, abstract operation <code>JO</code>.</p>
</div>
</li>
<li id="section-21">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-21">&#182;</a>
</div>
<p>Initializing stack of traversed objects.
Its done here since we only need them for objects and arrays comparison.</p>
</div>
<div class="content"><div class='highlight'><pre> aStack = aStack || [];
bStack = bStack || [];
<span class="hljs-keyword">var</span> length = aStack.<span class="hljs-property">length</span>;
<span class="hljs-keyword">while</span> (length--) {</pre></div></div>
</li>
<li id="section-22">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-22">&#182;</a>
</div>
<p>Linear search. Performance is inversely proportional to the number of
unique nested structures.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (aStack[length] === a) <span class="hljs-keyword">return</span> bStack[length] === b;
}</pre></div></div>
</li>
<li id="section-23">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-23">&#182;</a>
</div>
<p>Add the first object to the stack of traversed objects.</p>
</div>
<div class="content"><div class='highlight'><pre> aStack.<span class="hljs-title function_">push</span>(a);
bStack.<span class="hljs-title function_">push</span>(b);</pre></div></div>
</li>
<li id="section-24">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-24">&#182;</a>
</div>
<p>Recursively compare objects and arrays.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (areArrays) {</pre></div></div>
</li>
<li id="section-25">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-25">&#182;</a>
</div>
<p>Compare array lengths to determine if a deep comparison is necessary.</p>
</div>
<div class="content"><div class='highlight'><pre> length = a.<span class="hljs-property">length</span>;
<span class="hljs-keyword">if</span> (length !== b.<span class="hljs-property">length</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;</pre></div></div>
</li>
<li id="section-26">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-26">&#182;</a>
</div>
<p>Deep compare the contents, ignoring non-numeric properties.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">while</span> (length--) {
<span class="hljs-keyword">if</span> (!<span class="hljs-title function_">eq</span>(a[length], b[length], aStack, bStack)) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
} <span class="hljs-keyword">else</span> {</pre></div></div>
</li>
<li id="section-27">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-27">&#182;</a>
</div>
<p>Deep compare objects.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">var</span> _keys = <span class="hljs-title function_">keys</span>(a), key;
length = _keys.<span class="hljs-property">length</span>;</pre></div></div>
</li>
<li id="section-28">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-28">&#182;</a>
</div>
<p>Ensure that both objects contain the same number of properties before comparing deep equality.</p>
</div>
<div class="content"><div class='highlight'><pre> <span class="hljs-keyword">if</span> (<span class="hljs-title function_">keys</span>(b).<span class="hljs-property">length</span> !== length) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
<span class="hljs-keyword">while</span> (length--) {</pre></div></div>
</li>
<li id="section-29">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-29">&#182;</a>
</div>
<p>Deep compare each member</p>
</div>
<div class="content"><div class='highlight'><pre> key = _keys[length];
<span class="hljs-keyword">if</span> (!(<span class="hljs-title function_">has</span>(b, key) &amp;&amp; <span class="hljs-title function_">eq</span>(a[key], b[key], aStack, bStack))) <span class="hljs-keyword">return</span> <span class="hljs-literal">false</span>;
}
}</pre></div></div>
</li>
<li id="section-30">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-30">&#182;</a>
</div>
<p>Remove the first object from the stack of traversed objects.</p>
</div>
<div class="content"><div class='highlight'><pre> aStack.<span class="hljs-title function_">pop</span>();
bStack.<span class="hljs-title function_">pop</span>();
<span class="hljs-keyword">return</span> <span class="hljs-literal">true</span>;
}</pre></div></div>
</li>
<li id="section-31">
<div class="annotation">
<div class="pilwrap ">
<a class="pilcrow" href="#section-31">&#182;</a>
</div>
<p>Perform a deep comparison to check if two objects are equal.</p>
</div>
<div class="content"><div class='highlight'><pre><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-keyword">function</span> <span class="hljs-title function_">isEqual</span>(<span class="hljs-params">a, b</span>) {
<span class="hljs-keyword">return</span> <span class="hljs-title function_">eq</span>(a, b);
}</pre></div></div>
</li>
</ul>
</div>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
// We run a script at page load to inject the links after the fact.
// It would be more elegant to do this at page generation time, but
// unfortunately the docco infrastructure doesn't support this very well.
// Highlighted code is passed along as an unparsed HTML string, which would
// make this very tricky. In the script below, we exploit the fact that the
// HTML has already been parsed by the browser.
(function() {
// Define a regex for stripping the .html extension from anchor hrefs.
var extPattern = /\.html$/;
// Collect all module paths that we have an HTML page for.
var moduleMap = {};
$('#jump_page a.source').each(function() {
// Fortunately, translating anchor hrefs to ES module paths is easy,
// because both systems work relative to the current file by default.
var href = $(this).attr('href');
var path = href.replace(extPattern, '').split('/');
if (path[0] !== '..') path.unshift('.');
var normPath = path.join('/');
// Support both paths with and without extension.
moduleMap[normPath] = moduleMap[normPath + '.js'] = href;
});
// Find all 'from' keywords followed by a string (ES6 import statements).
$('.hljs-keyword').filter(function() {
var text = $(this).text();
return text === 'from' || text === 'import';
}).next('.hljs-string').each(function() {
// Finally, for each of these strings, replace it by a link if we have
// a matching HTML page.
var text = $(this).text();
var quote = text[0];
var path = text.slice(1, -1);
var matchingDoc = moduleMap[path];
if (!matchingDoc) return;
$(this).html(
quote + '<a href="' + matchingDoc + '">' + path + '</a>' + quote
);
});
}());
</script>
</body>
</html>