uTools-Manuals/docs/javascript/Guide/Keyed_collections.html

113 lines
9.2 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

<article id="wikiArticle">
<div> <div class="prevnext" style="text-align: right;">
<p><a href="Guide/Indexed_Collections" style="float: left;">« 上一页</a><a href="Guide/Working_with_Objects">下一页 »</a></p>
</div></div>
<p class="summary">这一章介绍由key值标记的数据容器Map 和 Set 对象承载的数据元素可以按照插入时的顺序被迭代遍历。</p>
<h2 id="映射">映射</h2>
<h3 id="Map对象"><code>Map</code>对象</h3>
<p>ECMAScript 2015 引入了一个新的数据结构来将一个值映射到另一个值。一个<a href="Reference/Map" title="此页面仍未被本地化, 期待您的翻译!"><code>Map</code></a>对象就是一个简单的键值对映射集合,可以按照数据插入时的顺序遍历所有的元素。</p>
<p>下面的代码演示了使用<code>Map</code>进行的一些基本操作。请参考<a href="Reference/Map" title="此页面仍未被本地化, 期待您的翻译!"><code>Map</code></a>以获取更多的样例和完整的 API。你可以使用<a href="Reference/Statements/for...of" title="for...of语句在可迭代对象包括 ArrayMapSetStringTypedArrayarguments 对象等等上创建一个迭代循环调用自定义迭代钩子并为每个不同属性的值执行语句"><code>for...of</code></a>循环来得到所有的<code>[key, value]</code></p>
<pre class="brush: js">var sayings = new Map();
sayings.set('dog', 'woof');
sayings.set('cat', 'meow');
sayings.set('elephant', 'toot');
sayings.size; // 3
sayings.get('fox'); // undefined
sayings.has('bird'); // false
sayings.delete('dog');
sayings.has('dog'); // false
for (var [key, value] of sayings) {
console.log(key + ' goes ' + value);
}
// "cat goes meow"
// "elephant goes toot"
sayings.clear();
sayings.size; // 0</pre>
<h3 id="Object和Map的比较"><code><font face="Consolas, Liberation Mono, Courier, monospace">Object</font></code><code>Map</code>的比较</h3>
<p>一般地,<a href="Reference/Global_Objects/Object" title="Object 构造函数创建一个对象包装器。">objects</a>会被用于将字符串类型映射到数值。<code>Object</code>允许设置键值对、根据键获取值、删除键、检测某个键是否存在。而<code>Map</code>具有更多的优势。</p>
<ul>
<li><code>Object</code>的键均为<code>Strings</code>类型,在<code>Map</code>里键可以是任意类型。</li>
<li>必须手动计算<code>Object</code>的尺寸,但是可以很容易地获取使用<code>Map</code>的尺寸。</li>
<li><code>Map</code>的遍历遵循元素的插入顺序。</li>
<li><code>Object</code>有原型,所以映射中有一些缺省的键。<font face="Open Sans, Arial, sans-serif"></font>可以用 <code>map = Object.create(null) 回避</code>)。</li>
</ul>
<p>这三条提示可以帮你决定用<code>Map</code>还是<code>Object</code></p>
<ul>
<li>如果键在运行时才能知道,或者所有的键类型相同,所有的值类型相同,那就使用<code>Map</code></li>
<li>如果需要将原始值存储为键,则使用<code>Map</code>,因为<code>Object</code>将每个键视为字符串,不管它是一个数字值、布尔值还是任何其他原始值。</li>
<li>如果需要对个别元素进行操作,使用<code>Object</code></li>
</ul>
<h3 id="WeakMap对象"><code>WeakMap</code>对象</h3>
<p><a href="Reference/WeakMap" title="此页面仍未被本地化, 期待您的翻译!"><code>WeakMap</code></a>对象也是键值对的集合。它的<strong>键必须是对象类型</strong>值可以是任意类型。它的键被弱保持也就是说当其键所指对象没有其他地方引用的时候它会被GC回收掉。<code>WeakMap</code>提供的接口与<code>Map</code>相同。</p>
<p><code>Map</code>对象不同的是,<code>WeakMap</code>的键是不可枚举的。不提供列出其键的方法。列表是否存在取决于垃圾回收器的状态,是不可预知的。</p>
<p>可以在"Why <em>Weak</em>Map?"<a href="Reference/WeakMap" title="此页面仍未被本地化, 期待您的翻译!"><code>WeakMap</code></a>查看更多信息和示例。</p>
<p><code>WeakMap</code>对象的一个用例是存储一个对象的私有数据或隐藏实施细节。Nick Fitzgerald 的博文<a class="external" href="http://fitzgeraldnick.com/weblog/53/" rel="noopener">"Hiding Implementation Details with ECMAScript 6 WeakMaps"</a>提供了一个例子。对象内部的私有数据和方法被存储在<code>WeakMap</code>类型的<code>privates</code>变量中。所有暴露出的原型和情况都是公开的,而其他内容都是外界不可访问的,因为模块并未导出<code>privates</code>对象。</p>
<pre class="brush: js">const privates = new WeakMap();
function Public() {
const me = {
// Private data goes here
};
privates.set(this, me);
}
Public.prototype.method = function () {
const me = privates.get(this);
// Do stuff with private data in `me`...
};
module.exports = Public;
</pre>
<h2 id="集合">集合</h2>
<h3 id="Set对象"><code>Set</code>对象</h3>
<p><a href="Reference/Global_Objects/Set" title="Set 对象允许你存储任何类型的唯一值无论是原始值或者是对象引用。"><code>Set</code></a>对象是一组值的集合,这些值是不重复的,可以按照添加顺序来遍历。</p>
<p>这里演示了<code>Set</code>的基本操作更多示例和完整API可以参考<a href="Reference/Global_Objects/Set" title="Set 对象允许你存储任何类型的唯一值无论是原始值或者是对象引用。"><code>Set</code></a></p>
<pre class="brush: js">var mySet = new Set();
mySet.add(1);
mySet.add("some text");
mySet.add("foo");
mySet.has(1); // true
mySet.delete("foo");
mySet.size; // 2
for (let item of mySet) console.log(item);
// 1
// "some text"
</pre>
<h3 id="数组和集合的转换">数组和集合的转换</h3>
<p>可以使用<a href="Reference/Global_Objects/Array/from" title="Array.from() 方法从一个类似数组或可迭代对象中创建一个新的数组实例。"><code>Array.from</code></a><a href="Reference/Operators/Spread_operator">展开操作符</a>来完成集合到数组的转换。同样,<code>Set</code>的构造器接受数组作为参数,可以完成从<code>Array</code><code>Set</code>的转换。需要重申的是,<code>Set</code>对象中的值不重复,所以数组转换为集合时,所有重复值将会被删除。</p>
<pre class="brush: js">Array.from(mySet);
[...mySet2];
mySet2 = new Set([1,2,3,4]);
</pre>
<h3 id="Array和Set的对比"><code>Array</code><code>Set</code>的对比</h3>
<p>一般情况下在JavaScript中使用数组来存储一组元素而新的集合对象有这些优势</p>
<ul>
<li>数组中用于判断元素是否存在的<a href="Reference/Global_Objects/Array/indexOf" title="indexOf()方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。"><code>indexOf</code></a> 函数效率低下。</li>
<li><code>Set</code>对象允许根据值删除元素,而数组中必须使用基于下标的 splice 方法。</li>
<li>数组的<code>indexOf</code>方法无法找到<a href="Reference/Global_Objects/NaN" title="全局属性 NaN 的值表示不是一个数字Not-A-Number。"><code>NaN</code></a>值。</li>
<li><code>Set</code>对象存储不重复的值,所以不需要手动处理包含重复值的情况。</li>
</ul>
<h3 id="WeakSet对象"><code>WeakSet</code>对象</h3>
<p><a href="Reference/Global_Objects/WeakSet" title="WeakSet 对象允许你将弱保持对象存储在一个集合中。"><code>WeakSet</code></a>对象是一组对象的集合。<code>WeakSet</code>中的对象不重复且不可枚举<font face="Consolas, Liberation Mono, Courier, monospace"></font></p>
<p><a href="Reference/Global_Objects/Set" title="Set 对象允许你存储任何类型的唯一值无论是原始值或者是对象引用。"><code>Set</code></a>对象的主要区别有:</p>
<ul>
<li><code>WeakSets</code>中的值必须是对象类型,不可以是别的类型</li>
<li><code>WeakSet</code>的“<em>weak</em>”指的是,对集合中的对象,如果不存在其他引用,那么该对象将可被垃圾回收。于是不存在一个当前可用对象组成的列表,所以<code>WeakSets</code>不可枚举</li>
</ul>
<p><code>WeakSet</code>的用例很有限比如使用DOM元素作为键来追踪它们而不必担心内存泄漏。</p>
<h2 id="Map的键和Set的值的等值判断"><code>Map</code>的键和<code>Set</code>的值的等值判断</h2>
<p><code>Map</code>的键和<code>Set</code>的值的等值判断都基于<a class="external" href="https://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevaluezero" rel="noopener">same-value-zero algorithm</a></p>
<ul>
<li>判断使用与<code>===</code>相似的规则。</li>
<li><code>-0</code><code>+0</code>相等。</li>
<li><a href="Reference/Global_Objects/NaN" title="全局属性 NaN 的值表示不是一个数字Not-A-Number。"><code>NaN</code></a>与自身相等(与<code>===</code>有所不同)。</li>
</ul>
<p></p><div class="prevnext" style="text-align: right;">
<p><a href="Guide/Indexed_Collections" style="float: left;">« 上一页</a><a href="Guide/Working_with_Objects">下一页 »</a></p>
</div><p></p>
</article>