diff options
Diffstat (limited to 'files/zh-cn/web/javascript/reference/global_objects/array')
43 files changed, 8073 insertions, 0 deletions
diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/@@iterator/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/@@iterator/index.html new file mode 100644 index 0000000000..31fe03d8b1 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/@@iterator/index.html @@ -0,0 +1,114 @@ +--- +title: 'Array.prototype[@@iterator]()' +slug: Web/JavaScript/Reference/Global_Objects/Array/@@iterator +tags: + - Array + - ECMAScript 2015 + - Iterator + - JavaScript + - Method + - Prototype + - 原型 + - 参考 + - 循环 + - 方法 + - 迭代 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/@@iterator +--- +<div>{{JSRef}}</div> + +<p><code><strong>@@iterator</strong></code> 属性和 {{jsxref("Array.prototype.values()", "Array.prototype.values()")}} 属性的初始值是同一个函数对象。</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js"><var>arr</var>[Symbol.iterator]()</pre> + +<h3 id="返回值">返回值</h3> + +<p>数组的 <strong>iterator </strong>方法,默认情况下,与 {{jsxref("Array.prototype.values()", "values()")}} 返回值相同, <code>arr[Symbol.iterator]</code> 则会返回 {{jsxref("Array.prototype.values()", "values()")}} 函数。</p> + +<h2 id="示例">示例</h2> + +<h3 id="使用_for...of_循环进行迭代"><font face="Open Sans, Arial, sans-serif">使用 </font><code>for...of</code> 循环进行迭代</h3> + +<pre class="brush: js">var arr = ['a', 'b', 'c', 'd', 'e']; +var eArr = arr[Symbol.iterator](); +// 浏览器必须支持 for...of 循环 +for (let letter of eArr) { + console.log(letter); +} +</pre> + +<h3 id="另一种迭代方式">另一种迭代方式</h3> + +<pre class="brush: js">var arr = ['a', 'b', 'c', 'd', 'e']; +var eArr = arr[Symbol.iterator](); +console.log(eArr.next().value); // a +console.log(eArr.next().value); // b +console.log(eArr.next().value); // c +console.log(eArr.next().value); // d +console.log(eArr.next().value); // e +</pre> + +<h3 id="Use_Case_for_brace_notation">Use Case for brace notation</h3> + +<p>The use case for this syntax over using the dot notation (<code>Array.prototype.values()</code>) is in a case where you don't know what object is going to be ahead of time. If you have a function that takes an iterator and then iterate over the value, but don't know if that Object is going to have a [Iterable].prototype.values method. This could be a built-in object like <a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String/@@iterator">String</a> object or a custom object.</p> + +<pre class="brush: js">function logIterable(it) { + var iterator = it[Symbol.iterator](); + // 浏览器必须支持 for...of 循环 + for (let letter of iterator) { + console.log(letter); + } +} + +// Array +logIterable(['a', 'b', 'c']); +// a +// b +// c + +// string +logIterable('abc'); +// a +// b +// c</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范名称</th> + <th scope="col">规范状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype-@@iterator', 'Array.prototype[@@iterator]()')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>首次定义</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype-@@iterator', 'Array.prototype[@@iterator]()')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Array.@@iterator")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.keys()")}}</li> + <li>{{jsxref("Array.prototype.entries()")}}</li> + <li>{{jsxref("Array.prototype.forEach()")}}</li> + <li>{{jsxref("Array.prototype.every()")}}</li> + <li>{{jsxref("Array.prototype.some()")}}</li> + <li>{{jsxref("Array.prototype.values()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/@@species/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/@@species/index.html new file mode 100644 index 0000000000..cc87927e5e --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/@@species/index.html @@ -0,0 +1,78 @@ +--- +title: 'get Array[@@species]' +slug: Web/JavaScript/Reference/Global_Objects/Array/@@species +tags: + - JavaScript + - 原型 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/@@species +--- +<div>{{JSRef}}</div> + +<p><code><strong>Array[@@species]</strong></code> 访问器属性返回 <code>Array</code> 的构造函数。</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox">Array[Symbol.species] +</pre> + +<h3 id="返回值">返回值</h3> + +<p>{{jsxref("Array")}} 的构造函数。</p> + +<h2 id="描述">描述</h2> + +<p><code>species</code> 访问器属性返回 <code>Array</code> 对象的默认构造函数。子类的构造函数可能会覆盖并改变构造函数的赋值。</p> + +<h2 id="示例">示例</h2> + +<p><code>species</code> 属性返回默认构造函数, 它用于 <code>Array</code> 对象的构造函数 <code>Array</code>:</p> + +<pre class="brush: js">Array[Symbol.species]; // function Array()</pre> + +<p>在继承类的对象中(例如你自定义的数组 <code>MyArray</code>),<code>MyArray</code> 的 <code>species</code> 属性返回的是 <code>MyArray</code> 这个构造函数. 然而你可能想要覆盖它,以便在你继承的对象 <code>MyArray</code> 中返回父类的构造函数 <code>Array</code> :</p> + +<pre class="brush: js">class MyArray extends Array { + // 重写 MyArray 的 species 属性到父类 Array 的构造函数 + static get [Symbol.species]() { return Array; } +}</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-get-array-@@species', 'get Array [ @@species ]')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-get-array-@@species', 'get Array [ @@species ]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.@@species")}}</p> +</div> +</div> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array")}}</li> + <li>{{jsxref("Symbol.species")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/@@unscopables/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/@@unscopables/index.html new file mode 100644 index 0000000000..b370dd1281 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/@@unscopables/index.html @@ -0,0 +1,89 @@ +--- +title: 'Array.prototype[@@unscopables]' +slug: Web/JavaScript/Reference/Global_Objects/Array/@@unscopables +tags: + - Array + - ECMAScript 2015 + - JavaScript + - Property + - Prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Array/@@unscopables +--- +<div>{{JSRef}}</div> + +<p>Symbol 属性 <code><strong>@@unscopable</strong></code> 包含了所有 ES2015 (ES6) 中新定义的、且并未被更早的 ECMAScript 标准收纳的属性名。这些属性被排除在由 <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with">with</a></code> 语句绑定的环境中。</p> + +<h2 id="语法">语法</h2> + +<pre class="brush: js"><var>arr</var>[Symbol.unscopables]</pre> + +<h2 id="描述">描述</h2> + +<p><code>with</code> 绑定中未包含的数组默认属性有:</p> + + + +<ul> + <li>{{jsxref("Array.prototype.copyWithin()", "copyWithin()")}}</li> + <li>{{jsxref("Array.prototype.entries()", "entries()")}}</li> + <li>{{jsxref("Array.prototype.fill()", "fill()")}}</li> + <li>{{jsxref("Array.prototype.find()", "find()")}}</li> + <li>{{jsxref("Array.prototype.findIndex()", "findIndex()")}}</li> + <li>{{jsxref("Array.prototype.includes()", "includes()")}}</li> + <li>{{jsxref("Array.prototype.keys()", "keys()")}}</li> + <li>{{jsxref("Array.prototype.values()", "values()")}}</li> +</ul> + +<p>参考 {{jsxref("Symbol.unscopables")}} 以了解如何为自定义的对象设置 <code>unscopables</code>。</p> + +<p>{{js_property_attributes(0,0,1)}}</p> + +<h2 id="示例">示例</h2> + +<p>以下的代码在 ES5 或更早的版本中能正常工作。然而 ECMAScript 2015 (ES6) 或之后的版本中新添加了 {{jsxref("Array.prototype.keys()")}} 这个方法。这意味着在 <code>with</code> 语句的作用域中,"keys"只能作为方法,而不能作为某个变量。这正是内置的 <code>@@unscopables</code> 即 <code>Array.prototype[@@unscopables]</code> symbol 属性所要解决的问题:防止某些数组方法被添加到 <code>with</code> 语句的作用域内。</p> + +<pre class="brush: js">var keys = []; + +with(Array.prototype) { + keys.push("something"); +} + +Object.keys(Array.prototype[Symbol.unscopables]); +// ["copyWithin", "entries", "fill", "find", "findIndex", +// "includes", "keys", "values"]</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范名称</th> + <th scope="col">规范状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype-@@unscopables', 'Array.prototype[@@unscopables]')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>首次定义</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype-@@unscopables', 'Array.prototype[@@unscopables]')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.@@unscopables")}}</p> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Symbol.unscopables")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/concat/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/concat/index.html new file mode 100644 index 0000000000..22911acb9d --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/concat/index.html @@ -0,0 +1,158 @@ +--- +title: Array.prototype.concat() +slug: Web/JavaScript/Reference/Global_Objects/Array/concat +tags: + - JavaScript + - 原型 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/concat +--- +<div>{{JSRef}}</div> + +<p> <code><strong>concat()</strong></code> 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。</p> + +<p>{{EmbedInteractiveExample("pages/js/array-concat.html")}}</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate">var <var>new_array</var> = <var>old_array</var>.concat(<var>value1</var>[, <var>value2</var>[, ...[, <var>valueN</var>]]])</pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>value<em>N</em></code>{{optional_inline}}</dt> + <dd>数组和/或值,将被合并到一个新的数组中。如果省略了所有 <code>valueN</code> 参数,则 <code>concat</code> 会返回调用此方法的现存数组的一个浅拷贝。详情请参阅下文描述。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>新的 {{jsxref("Array")}} 实例。</p> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>concat</code>方法创建一个新的数组,它由被调用的对象中的元素组成,每个参数的顺序依次是该参数的元素(如果参数是数组)或参数本身(如果参数不是数组)。它不会递归到嵌套数组参数中。</p> + +<p><code>concat</code>方法不会改变<code>this</code>或任何作为参数提供的数组,而是返回一个浅拷贝,它包含与原始数组相结合的相同元素的副本。 原始数组的元素将复制到新数组中,如下所示:</p> + +<ul> + <li>对象引用(而不是实际对象):<code>concat</code>将对象引用复制到新数组中。 原始数组和新数组都引用相同的对象。 也就是说,如果引用的对象被修改,则更改对于新数组和原始数组都是可见的。 这包括也是数组的数组参数的元素。</li> +</ul> + +<ul> + <li>数据类型如字符串,数字和布尔(不是{{jsxref("Global_Objects/String", "String")}},{{jsxref("Global_Objects/Number", "Number")}} 和 {{jsxref("Global_Objects/Boolean", "Boolean")}} 对象):<code>concat</code>将字符串和数字的值复制到新数组中。</li> +</ul> + +<div class="note"> +<p><strong>注意:</strong>数组/值在连接时保持不变。此外,对于新数组的任何操作(仅当元素不是对象引用时)都不会对原始数组产生影响,反之亦然。</p> +</div> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="Example_Concatenating_two_arrays" name="Example:_Concatenating_two_arrays">连接两个数组</h3> + +<p>以下代码将两个数组合并为一个新数组:</p> + +<pre class="brush: js notranslate">var alpha = ['a', 'b', 'c']; +var numeric = [1, 2, 3]; + +alpha.concat(numeric); +// result in ['a', 'b', 'c', 1, 2, 3]</pre> + +<h3 id="Example_Concatenating_three_arrays" name="Example:_Concatenating_three_arrays">连接三个数组</h3> + +<p>以下代码将三个数组合并为一个新数组:</p> + +<pre class="brush: js notranslate">var num1 = [1, 2, 3], + num2 = [4, 5, 6], + num3 = [7, 8, 9]; + +var nums = num1.concat(num2, num3); + +console.log(nums); +// results in [1, 2, 3, 4, 5, 6, 7, 8, 9]</pre> + +<h3 id="Example_Concatenating_values_to_an_array" name="Example:_Concatenating_values_to_an_array">将值连接到数组</h3> + +<p>以下代码将三个值连接到数组:</p> + +<pre class="brush: js notranslate">var alpha = ['a', 'b', 'c']; + +var alphaNumeric = alpha.concat(1, [2, 3]); + +console.log(alphaNumeric); +// results in ['a', 'b', 'c', 1, 2, 3]</pre> + +<h3 id="合并嵌套数组">合并嵌套数组</h3> + +<p>以下代码合并数组并保留引用:</p> + +<pre class="brush: js notranslate">var num1 = [[1]]; +var num2 = [2, [3]]; +var num3=[5,[6]]; + +var nums = num1.concat(num2); + +console.log(nums); +// results is [[1], 2, [3]] + +var nums2=num1.concat(4,num3); + +console.log(nums2) +// results is [[1], 4, 5,[6]] + +// modify the first element of num1 +num1[0].push(4); + +console.log(nums); +// results is [[1, 4], 2, [3]]</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Initial definition. Implemented in JavaScript 1.2.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.4', 'Array.prototype.concat')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.concat', 'Array.prototype.concat')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.concat', 'Array.prototype.concat')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容">浏览器兼容</h2> + +<div class="hidden"> +<p>The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p> +</div> + +<p>{{Compat("javascript.builtins.Array.concat")}}</p> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array.push", "push")}} / {{jsxref("Array.pop", "pop")}} — add/remove elements from the end of the array</li> + <li>{{jsxref("Array.unshift", "unshift")}} / {{jsxref("Array.shift", "shift")}} — add/remove elements from the beginning of the array</li> + <li>{{jsxref("Array.splice", "splice")}} — add/remove elements from the specified location of the array</li> + <li>{{jsxref("String.prototype.concat()")}}</li> + <li>{{jsxref("Symbol.isConcatSpreadable")}} – control flattening.</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/copywithin/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/copywithin/index.html new file mode 100644 index 0000000000..b19fa2fc56 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/copywithin/index.html @@ -0,0 +1,190 @@ +--- +title: Array.prototype.copyWithin() +slug: Web/JavaScript/Reference/Global_Objects/Array/copyWithin +tags: + - ECMAScript 2015 + - JavaScript + - polyfill + - 原型 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/copyWithin +--- +<div>{{JSRef}}</div> + +<div><code><strong>copyWithin()</strong></code> 方法浅复制数组的一部分到同一数组中的另一个位置,并返回它,不会改变原数组的长度。</div> + +<div>{{EmbedInteractiveExample("pages/js/array-copywithin.html")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox"><var>arr</var>.copyWithin(<var>target[</var>, <var>start[</var>, <var>end]]</var>) +</pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>target</code></dt> + <dd>0 为基底的索引,复制序列到该位置。如果是负数,<code>target</code> 将从末尾开始计算。</dd> + <dd>如果 <code>target</code> 大于等于 <code>arr.length</code>,将会不发生拷贝。如果 <code>target</code> 在 <code>start</code> 之后,复制的序列将被修改以符合 <code>arr.length</code>。</dd> + <dt><code>start</code></dt> + <dd>0 为基底的索引,开始复制元素的起始位置。如果是负数,<code>start</code> 将从末尾开始计算。</dd> + <dd>如果 <code>start</code> 被忽略,<code>copyWithin</code> 将会从0开始复制。</dd> + <dt><code>end</code></dt> + <dd>0 为基底的索引,开始复制元素的结束位置。<code>copyWithin</code> 将会拷贝到该位置,但不包括 <code>end</code> 这个位置的元素。如果是负数, <code>end</code> 将从末尾开始计算。</dd> + <dd>如果 <code>end</code> 被忽略,<code>copyWithin</code> 方法将会一直复制至数组结尾(默认为 <code>arr.length</code>)。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>改变后的数组。</p> + +<h2 id="描述">描述</h2> + +<p>参数 target、start 和 end 必须为整数。</p> + +<p>如果 start 为负,则其指定的索引位置等同于 length+start,length 为数组的长度。end 也是如此。</p> + +<p>copyWithin 方法不要求其 this 值必须是一个数组对象;除此之外,copyWithin 是一个可变方法,它可以改变 this 对象本身,并且返回它,而不仅仅是它的拷贝。</p> + +<p><code>copyWithin</code> 就像 C 和 C++ 的 <code>memcpy</code> 函数一样,且它是用来移动 {{jsxref("Array")}} 或者 {{jsxref("TypedArray")}} 数据的一个高性能的方法。复制以及粘贴序列这两者是为一体的操作;即使复制和粘贴区域重叠,粘贴的序列也会有拷贝来的值。</p> + +<p><code>copyWithin</code><strong> </strong>函数被设计为通用式的,其不要求其 <code>this</code> 值必须是一个{{jsxref("Array", "数组")}}对象。</p> + +<p><code>copyWithin</code> 是一个可变方法,它不会改变 this 的长度 length,但是会改变 this 本身的内容,且需要时会创建新的属性。</p> + +<h2 id="例子">例子</h2> + +<pre><code>[1, 2, 3, 4, 5].copyWithin(-2) +// [1, 2, 3, 1, 2] + +[1, 2, 3, 4, 5].copyWithin(0, 3) +// [4, 5, 3, 4, 5] + +[1, 2, 3, 4, 5].copyWithin(0, 3, 4) +// [4, 2, 3, 4, 5] + +[1, 2, 3, 4, 5].copyWithin(-2, -3, -1) +// [1, 2, 3, 3, 4]</code> + +[].copyWithin.call({length: 5, 3: 1}, 0, 3); +// {0: 1, 3: 1, length: 5} + +// ES2015 Typed Arrays are subclasses of Array +var i32a = new Int32Array([1, 2, 3, 4, 5]); + +i32a.copyWithin(0, 2); +// Int32Array [3, 4, 5, 4, 5] + +// On platforms that are not yet ES2015 compliant: +[].copyWithin.call(new Int32Array([1, 2, 3, 4, 5]), 0, 3, 4); +// Int32Array [4, 2, 3, 4, 5] +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<pre class="brush: js">if (!Array.prototype.copyWithin) { + Array.prototype.copyWithin = function(target, start/*, end*/) { + // Steps 1-2. + if (this == null) { + throw new TypeError('this is null or not defined'); + } + + var O = Object(this); + + // Steps 3-5. + var len = O.length >>> 0; + + // Steps 6-8. + var relativeTarget = target >> 0; + + var to = relativeTarget < 0 ? + Math.max(len + relativeTarget, 0) : + Math.min(relativeTarget, len); + + // Steps 9-11. + var relativeStart = start >> 0; + + var from = relativeStart < 0 ? + Math.max(len + relativeStart, 0) : + Math.min(relativeStart, len); + + // Steps 12-14. + var end = arguments[2]; + var relativeEnd = end === undefined ? len : end >> 0; + + var final = relativeEnd < 0 ? + Math.max(len + relativeEnd, 0) : + Math.min(relativeEnd, len); + + // Step 15. + var count = Math.min(final - from, len - to); + + // Steps 16-17. + var direction = 1; + + if (from < to && to < (from + count)) { + direction = -1; + from += count - 1; + to += count - 1; + } + + // Step 18. + while (count > 0) { + if (from in O) { + O[to] = O[from]; + } else { + delete O[to]; + } + + from += direction; + to += direction; + count--; + } + + // Step 19. + return O; + }; +} +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-array.prototype.copywithin', 'Array.prototype.copyWithin')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES2016', '#sec-array.prototype.copywithin', 'Array.prototype.copyWithin')}}</td> + <td>{{Spec2('ES2016')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.copywithin', 'Array.prototype.copyWithin')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Array.copyWithin")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/entries/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/entries/index.html new file mode 100644 index 0000000000..6d2d0018a8 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/entries/index.html @@ -0,0 +1,154 @@ +--- +title: Array.prototype.entries() +slug: Web/JavaScript/Reference/Global_Objects/Array/entries +tags: + - Array.prototype.entries() +translation_of: Web/JavaScript/Reference/Global_Objects/Array/entries +--- +<div>{{JSRef}}</div> + +<p><code><strong>entries()</strong></code> 方法返回一个新的<strong>Array Iterator</strong>对象,该对象包含数组中每个索引的键/值对。</p> + +<p>{{EmbedInteractiveExample("pages/js/array-entries.html")}}</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox"><code><em>arr</em>.entries()</code></pre> + +<h3 id="返回值">返回值</h3> + +<p>一个新的 {{jsxref("Array")}} 迭代器对象。<a href="http://www.ecma-international.org/ecma-262/6.0/#sec-createarrayiterator">Array Iterator</a>是对象,它的原型(__proto__:Array Iterator)上有一个<a href="http://www.ecma-international.org/ecma-262/6.0/#sec-%arrayiteratorprototype%.next">next</a>方法,可用用于遍历迭代器取得原数组的[key,value]。</p> + +<h2 id="示例">示例</h2> + +<h3 id="1、_Array_Iterator">1、 Array Iterator</h3> + +<pre class="brush: js">var arr = ["a", "b", "c"]; +var iterator = arr.entries(); +console.log(iterator); + +/*<em>Array Iterator {}</em> + __proto__:Array Iterator + next:<em>ƒ next()</em> + Symbol(Symbol.toStringTag):"Array Iterator" + __proto__:<em>Object</em> +*/</pre> + +<h3 id="2、iterator.next()">2、iterator.next()</h3> + +<pre class="brush: js">var arr = ["a", "b", "c"]; +var iterator = arr.entries(); +console.log(iterator.next()); + +/*{value: Array(2), done: false} + done:false + value:(2) [0, "a"] + __proto__: Object +*/ +// iterator.next()返回一个对象,对于有元素的数组, +// 是next{ value: Array(2), done: false }; +// next.done 用于指示迭代器是否完成:在每次迭代时进行更新而且都是false, +// 直到迭代器结束done才是true。 +// next.value是一个["key","value"]的数组,是返回的迭代器中的元素值。 +</pre> + +<h3 id="3、iterator.next方法运行">3、iterator.next方法运行</h3> + +<pre class="brush: js">var arr = ["a", "b", "c"]; +var iter = arr.entries(); +var a = []; + +// for(var i=0; i< arr.length; i++){ // 实际使用的是这个 +for(var i=0; i< arr.length+1; i++){ // 注意,是length+1,比数组的长度大 + var tem = iter.next(); // 每次迭代时更新next + console.log(tem.done); // 这里可以看到更新后的done都是false + if(tem.done !== true){ // 遍历迭代器结束done才是true + console.log(tem.value); + a[i]=tem.value; + } +} + +console.log(a); // 遍历完毕,输出next.value的数组</pre> + +<h3 id="4、二维数组按行排序">4、二维数组按行排序</h3> + +<pre class="brush: js">function sortArr(arr) { + var goNext = true; + var entries = arr.entries(); + while (goNext) { + var result = entries.next(); + if (result.done !== true) { + result.value[1].sort((a, b) => a - b); + goNext = true; + } else { + goNext = false; + } + } + return arr; +} + +var arr = [[1,34],[456,2,3,44,234],[4567,1,4,5,6],[34,78,23,1]]; +sortArr(arr); + +/*(4) [Array(2), Array(5), Array(5), Array(4)] + 0:(2) [1, 34] + 1:(5) [2, 3, 44, 234, 456] + 2:(5) [1, 4, 5, 6, 4567] + 3:(4) [1, 23, 34, 78] + length:4 + __proto__:Array(0) +*/ +</pre> + +<h3 id="5、使用for…of_循环">5、使用<a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of">for…of</a> 循环</h3> + +<pre class="brush:js">var arr = ["a", "b", "c"]; +var iterator = arr.entries(); +// undefined + +for (let e of iterator) { + console.log(e); +} + +// [0, "a"] +// [1, "b"] +// [2, "c"] +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范名称</th> + <th scope="col">规范状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.entries', 'Array.prototype.entries')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>首次定义</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.entries")}}</p> +</div> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.keys()")}}</li> + <li>{{jsxref("Array.prototype.forEach()")}}</li> + <li>{{jsxref("Array.prototype.every()")}}</li> + <li>{{jsxref("Array.prototype.some()")}}</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of">for...of</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">Iteration protocols</a></li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/every/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/every/index.html new file mode 100644 index 0000000000..a64c25b43d --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/every/index.html @@ -0,0 +1,194 @@ +--- +title: Array.prototype.every() +slug: Web/JavaScript/Reference/Global_Objects/Array/every +tags: + - ECMAScript 5 + - JavaScript + - polyfill + - 原型 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/every +--- +<div>{{JSRef}}</div> + +<p><code><strong>every()</strong></code> 方法测试一个数组内的所有元素是否都能通过某个指定函数的测试。它返回一个布尔值。</p> + +<div class="note"> +<p><strong>注意</strong>:若收到一个空数组,此方法在一切情况下都会返回 <code>true</code>。</p> +</div> + +<div>{{EmbedInteractiveExample("pages/js/array-every.html")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre class="notranslate"><var>arr</var>.every(<var>callback</var>(<var>element</var>[, <var>index</var>[, <var>array</var>]])[, <var>thisArg</var>])</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>用来测试每个元素的函数,它可以接收三个参数: + <dl> + <dt><code>element</code></dt> + <dd>用于测试的当前值。</dd> + <dt><code>index</code>{{Optional_inline}}</dt> + <dd>用于测试的当前值的索引。</dd> + <dt><code>array</code>{{Optional_inline}}</dt> + <dd>调用 <code>every</code> 的当前数组。</dd> + </dl> + </dd> + <dt><code>thisArg</code></dt> + <dd>执行 <code>callback</code> 时使用的 <code>this</code> 值。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>如果回调函数的每一次返回都为 {{Glossary("truthy")}} 值,返回 <code><strong>true</strong></code> ,否则返回 <code><strong>false</strong></code>。</p> + +<h2 id="描述">描述</h2> + +<p><code>every</code> 方法为数组中的每个元素执行一次 <code>callback</code> 函数,直到它找到一个会使 <code>callback</code> 返回 {{Glossary("falsy")}} 的元素。如果发现了一个这样的元素,<code>every</code> 方法将会立即返回 <code>false</code>。否则,<code>callback</code> 为每一个元素返回 <code>true</code>,<code>every</code> 就会返回 <code>true</code>。<code>callback</code> 只会为那些已经被赋值的索引调用。不会为那些被删除或从未被赋值的索引调用。</p> + +<p><code>callback</code> 在被调用时可传入三个参数:元素值,元素的索引,原数组。</p> + +<p>如果为 <code>every</code> 提供一个 <code>thisArg</code> 参数,则该参数为调用 <code>callback</code> 时的 <code>this</code> 值。如果省略该参数,则 <code>callback</code> 被调用时的 <code>this</code> 值,在非严格模式下为全局对象,在严格模式下传入 <code>undefined</code>。详见 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Operators/this">this</a></code> 条目。</p> + +<p><code>every</code> 不会改变原数组。</p> + +<p><code>every</code> 遍历的元素范围在第一次调用 <code>callback</code> 之前就已确定了。在调用 <code>every</code> 之后添加到数组中的元素不会被 <code>callback</code> 访问到。如果数组中存在的元素被更改,则他们传入 <code>callback</code> 的值是 <code>every</code> 访问到他们那一刻的值。那些被删除的元素或从来未被赋值的元素将不会被访问到。</p> + +<p><code>every</code> 和数学中的"所有"类似,当所有的元素都符合条件才会返回<code>true</code>。正因如此,若传入一个空数组,无论如何都会返回 <code>true</code>。(这种情况属于<a href="http://en.wikipedia.org/wiki/Vacuous_truth">无条件正确</a>:正因为一个<a href="https://en.wikipedia.org/wiki/Empty_set#Properties">空集合</a>没有元素,所以它其中的所有元素都符合给定的条件。)</p> + +<h2 id="例子">例子</h2> + +<h3 id="检测所有数组元素的大小">检测所有数组元素的大小</h3> + +<p>下例检测数组中的所有元素是否都大于 10。</p> + +<pre class="brush: js notranslate">function isBigEnough(element, index, array) { + return element >= 10; +} +[12, 5, 8, 130, 44].every(isBigEnough); // false +[12, 54, 18, 130, 44].every(isBigEnough); // true +</pre> + +<h3 id="使用箭头函数">使用箭头函数</h3> + +<p><a href="/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭头函数</a>为上面的检测过程提供了更简短的语法。</p> + +<pre class="brush: js notranslate">[12, 5, 8, 130, 44].every(x => x >= 10); // false +[12, 54, 18, 130, 44].every(x => x >= 10); // true</pre> + +<h2 id="兼容旧环境(Polyfill)">兼容旧环境(Polyfill)</h2> + +<p>在 ECMA-262 第 5 版时,<code>every</code> 被添加进 ECMA-262 标准;因此,在某些实现环境中,它尚未被支持。你可以把下面的代码放到脚本的开头来解决此问题,该代码允许在那些没有原生支持 <code>every</code> 的实现环境中使用它。该算法是 ECMA-262 第 5 版中指定的算法,它假定 <code>Object</code> 和 <code>TypeError</code> 拥有它们的初始值,且 <code>fun.call</code> 等价于 {{jsxref("Function.prototype.call")}}。</p> + +<pre class="brush: js notranslate">if (!Array.prototype.every) { + Array.prototype.every = function(callbackfn, thisArg) { + 'use strict'; + var T, k; + + if (this == null) { + throw new TypeError('this is null or not defined'); + } + + // 1. Let O be the result of calling ToObject passing the this + // value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get internal method + // of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If IsCallable(callbackfn) is false, throw a TypeError exception. + if (typeof callbackfn !== 'function') { + throw new TypeError(); + } + + // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 1) { + T = thisArg; + } + + // 6. Let k be 0. + k = 0; + + // 7. Repeat, while k < len + while (k < len) { + + var kValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty internal + // method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal method + // of O with argument Pk. + kValue = O[k]; + + // ii. Let testResult be the result of calling the Call internal method + // of callbackfn with T as the this value and argument list + // containing kValue, k, and O. + var testResult = callbackfn.call(T, kValue, k, O); + + // iii. If ToBoolean(testResult) is false, return false. + if (!testResult) { + return false; + } + } + k++; + } + return true; + }; +} +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.16', 'Array.prototype.every')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.6.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.every', 'Array.prototype.every')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.every', 'Array.prototype.every')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Array.every")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.forEach()")}}</li> + <li>{{jsxref("Array.prototype.some()")}}</li> + <li>{{jsxref("Array.prototype.find()")}}</li> + <li>{{jsxref("TypedArray.prototype.every()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/fill/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/fill/index.html new file mode 100644 index 0000000000..2acc9d6d73 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/fill/index.html @@ -0,0 +1,153 @@ +--- +title: Array.prototype.fill() +slug: Web/JavaScript/Reference/Global_Objects/Array/fill +tags: + - Array + - ECMAScript6 + - JavaScript + - Method + - polyfill +translation_of: Web/JavaScript/Reference/Global_Objects/Array/fill +--- +<div>{{JSRef}} </div> + +<p><code><strong>fill()</strong></code> 方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。</p> + +<p>{{EmbedInteractiveExample("pages/js/array-fill.html")}}</p> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre><var>arr</var>.fill(<var>value[</var>, <var>start[<var>, <var>end]]</var>)</var></var></pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>value</code></dt> + <dd>用来填充数组元素的值。</dd> + <dt><code>start</code> {{optional_inline}}</dt> + <dd>起始索引,默认值为0。</dd> + <dt><code>end</code> {{optional_inline}}</dt> + <dd>终止索引,默认值为 <code>this.length</code>。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>修改后的数组。</p> + +<h2 id="Description" name="Description">描述</h2> + +<p><strong><code>fill</code></strong> 方法接受三个参数 <code>value</code>, <code>start</code> 以及 <code>end</code>.<span> <code>start</code> 和 <code>end</code> 参数是可选的, 其默认值分别为 <code>0</code> 和 <code>this</code> 对象的 <code>length </code></span>属性值。</p> + +<p><span>如果 <code>start</code> 是个负数, 则开始索引会被自动计算成为 <code>length+start</code></span>, 其中<span> <code>length</code> 是 </span><code>this</code><span> 对象的 </span><code>length </code>属性值。<span>如果 </span><code>end</code><span> 是个负数, 则结束索引会被自动计算成为 </span><code>length+end</code>。</p> + +<p><span><code><strong>fill</strong></code> 方法故意被设计成通用方法, 该方法不要求 <code>this</code> 是数组对象。</span></p> + +<p><code><strong style="line-height: 1.5;">fill</strong></code><span style="line-height: 1.5;"> 方法是个可变方法, 它会改变调用它的 <code>this</code> 对象本身, 然后返回它, 而并不是返回一个副本。</span></p> + +<p>当一个对象被传递给 <strong><code>fill</code></strong>方法的时候, 填充数组的是这个对象的引用。</p> + +<h2 id="示例">示例</h2> + +<pre class="brush: js">[1, 2, 3].fill(4); // [4, 4, 4] +[1, 2, 3].fill(4, 1); // [1, 4, 4] +[1, 2, 3].fill(4, 1, 2); // [1, 4, 3] +[1, 2, 3].fill(4, 1, 1); // [1, 2, 3] +[1, 2, 3].fill(4, 3, 3); // [1, 2, 3] +[1, 2, 3].fill(4, -3, -2); // [4, 2, 3] +[1, 2, 3].fill(4, NaN, NaN); // [1, 2, 3] +[1, 2, 3].fill(4, 3, 5); // [1, 2, 3] +Array(3).fill(4); // [4, 4, 4] +[].fill.call({ length: 3 }, 4); // {0: 4, 1: 4, 2: 4, length: 3} + +// Objects by reference. +var arr = Array(3).fill({}) // [{}, {}, {}]; +// 需要注意如果fill的参数为引用类型,会导致都执行都一个引用类型 +// 如 arr[0] === arr[1] 为true +arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<pre class="brush: js">if (!Array.prototype.fill) { + Object.defineProperty(Array.prototype, 'fill', { + value: function(value) { + + // Steps 1-2. + if (this == null) { + throw new TypeError('this is null or not defined'); + } + + var O = Object(this); + + // Steps 3-5. + var len = O.length >>> 0; + + // Steps 6-7. + var start = arguments[1]; + var relativeStart = start >> 0; + + // Step 8. + var k = relativeStart < 0 ? + Math.max(len + relativeStart, 0) : + Math.min(relativeStart, len); + + // Steps 9-10. + var end = arguments[2]; + var relativeEnd = end === undefined ? + len : end >> 0; + + // Step 11. + var final = relativeEnd < 0 ? + Math.max(len + relativeEnd, 0) : + Math.min(relativeEnd, len); + + // Step 12. + while (k < final) { + O[k] = value; + k++; + } + + // Step 13. + return O; + } + }); +} +</pre> + +<p>如果你确实需要维护已过时的不支持 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">Object.defineProperty</a></code> 的 JavaScript 引擎,那么最好完全不向 <code>Array.prototype</code> 添加方法,因为你不能使它不可枚举。</p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">注释</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.fill', 'Array.prototype.fill')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>最初定义。</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.fill', 'Array.prototype.fill')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div>{{Compat("javascript.builtins.Array.fill")}}</div> + +<div id="compat-mobile"> + +</div> + +<h2 id="See_also" name="See_also">相关</h2> + +<ul> + <li>{{jsxref("Array")}}</li> + <li>{{jsxref("TypedArray.prototype.fill()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.html new file mode 100644 index 0000000000..c23bf5cb98 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.html @@ -0,0 +1,234 @@ +--- +title: Array.prototype.filter() +slug: Web/JavaScript/Reference/Global_Objects/Array/filter +tags: + - ECMAScript 5 + - JavaScript + - Prototype + - polyfill + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/filter +--- +<div>{{JSRef}}</div> + +<p><code><strong>filter()</strong></code> 方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。 </p> + +<p>{{EmbedInteractiveExample("pages/js/array-filter.html")}}</p> + + + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate"><var>var newArray = arr</var>.filter(<var>callback(element[, index[, array]])</var>[, <var>thisArg</var>])</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>用来测试数组的每个元素的函数。返回 <code>true</code> 表示该元素通过测试,保留该元素,<code>false</code> 则不保留。它接受以下三个参数:</dd> + <dd> + <dl> + <dt><code>element</code></dt> + <dd>数组中当前正在处理的元素。</dd> + <dt><code>index</code>{{optional_inline}}</dt> + <dd>正在处理的元素在数组中的索引。</dd> + <dt><code>array</code>{{optional_inline}}</dt> + <dd>调用了 <code>filter</code> 的数组本身。</dd> + </dl> + </dd> + <dt><code>thisArg</code>{{optional_inline}}</dt> + <dd>执行 <code>callback</code> 时,用于 <code>this</code> 的值。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。</p> + +<h2 id="描述">描述</h2> + +<p><code>filter</code> 为数组中的每个元素调用一次 <code>callback</code> 函数,并利用所有使得 <code>callback</code> 返回 true 或<a href="/zh-CN/docs/Glossary/Truthy">等价于 true 的值</a>的元素创建一个新数组。<code>callback</code> 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 <code>callback</code> 测试的元素会被跳过,不会被包含在新数组中。</p> + +<p><code>callback</code> 被调用时传入三个参数:</p> + +<ol> + <li>元素的值</li> + <li>元素的索引</li> + <li>被遍历的数组本身</li> +</ol> + +<p>如果为 <code>filter</code> 提供一个 <code>thisArg</code> 参数,则它会被作为 <code>callback</code> 被调用时的 <code>this</code> 值。否则,<code>callback</code> 的 <code>this</code> 值在非严格模式下将是全局对象,严格模式下为 <code>undefined</code>。<code>callback</code> 函数最终观察到的 <code>this</code> 值是根据<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/this">通常函数所看到的 "this"的规则</a>确定的。</p> + +<p><code>filter</code> 不会改变原数组,它返回过滤后的新数组。</p> + +<p><code>filter</code> 遍历的元素范围在第一次调用 <code>callback</code> 之前就已经确定了。在调用 <code>filter</code> 之后被添加到数组中的元素不会被 <code>filter</code> 遍历到。如果已经存在的元素被改变了,则他们传入 <code>callback</code> 的值是 <code>filter</code> 遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。</p> + +<h2 id="示例">示例</h2> + +<h3 id="筛选排除所有较小的值">筛选排除所有较小的值</h3> + +<p>下例使用 <code>filter</code> 创建了一个新数组,该数组的元素由原数组中值大于 10 的元素组成。</p> + +<pre class="brush: js notranslate">function isBigEnough(element) { + return element >= 10; +} +var filtered = [12, 5, 8, 130, 44].filter(isBigEnough); +// filtered is [12, 130, 44] +</pre> + +<h3 id="过滤_JSON_中的无效条目">过滤 JSON 中的无效条目</h3> + +<p>以下示例使用 <code>filter()</code> 创建具有非零 <code>id</code> 的元素的 json。</p> + +<pre class="brush: js notranslate">var arr = [ + { id: 15 }, + { id: -1 }, + { id: 0 }, + { id: 3 }, + { id: 12.2 }, + { }, + { id: null }, + { id: NaN }, + { id: 'undefined' } +]; + +var invalidEntries = 0; + +function isNumber(obj) { + return obj !== undefined && typeof(obj) === 'number' && !isNaN(obj); +} + +function filterByID(item) { + if (isNumber(item.id) && item.id !== 0) { + return true; + } + invalidEntries++; + return false; +} + +var arrByID = arr.filter(filterByID); + +console.log('Filtered Array\n', arrByID); +// Filtered Array +// [{ id: 15 }, { id: -1 }, { id: 3 }, { id: 12.2 }] + +console.log('Number of Invalid Entries = ', invalidEntries); +// Number of Invalid Entries = 5 +</pre> + +<h3 id="在数组中搜索">在数组中搜索</h3> + +<p>下例使用 <code>filter()</code> 根据搜索条件来过滤数组内容。</p> + +<pre class="brush: js notranslate">var fruits = ['apple', 'banana', 'grapes', 'mango', 'orange']; + +/** + * Array filters items based on search criteria (query) + */ +function filterItems(query) { + return fruits.filter(function(el) { + return el.toLowerCase().indexOf(query.toLowerCase()) > -1; + }) +} + +console.log(filterItems('ap')); // ['apple', 'grapes'] +console.log(filterItems('an')); // ['banana', 'mango', 'orange']</pre> + +<h4 id="ES2015_实现">ES2015 实现</h4> + +<pre class="brush: js notranslate">const fruits = ['apple', 'banana', 'grapes', 'mango', 'orange']; + +/** + * Array filters items based on search criteria (query) + */ +const filterItems = (query) => { + return fruits.filter((el) => + el.toLowerCase().indexOf(query.toLowerCase()) > -1 + ); +} + +console.log(filterItems('ap')); // ['apple', 'grapes'] +console.log(filterItems('an')); // ['banana', 'mango', 'orange'] + +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p><code>filter</code> 被添加到 ECMA-262 标准第 5 版中,因此在某些实现环境中不被支持。可以把下面的代码插入到脚本的开头来解决此问题,该代码允许在那些没有原生支持 <code>filter</code> 的实现环境中使用它。该算法是 ECMA-262 第 5 版中指定的算法,假定 <code>fn.call</code> 等价于 {{jsxref("Function.prototype.call")}} 的初始值,且 {{jsxref("Array.prototype.push")}} 拥有它的初始值。</p> + +<pre class="brush: js notranslate">if (!Array.prototype.filter){ + Array.prototype.filter = function(func, thisArg) { + 'use strict'; + if ( ! ((typeof func === 'Function' || typeof func === 'function') && this) ) + throw new TypeError(); + + var len = this.length >>> 0, + res = new Array(len), // preallocate array + t = this, c = 0, i = -1; + if (thisArg === undefined){ + while (++i !== len){ + // checks to see if the key was set + if (i in this){ + if (func(t[i], i, t)){ + res[c++] = t[i]; + } + } + } + } + else{ + while (++i !== len){ + // checks to see if the key was set + if (i in this){ + if (func.call(thisArg, t[i], i, t)){ + res[c++] = t[i]; + } + } + } + } + + res.length = c; // shrink down array to proper size + return res; + }; +}</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.20', 'Array.prototype.filter')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.6.</td> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-array.prototype.filter', 'Array.prototype.filter')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.filter', 'Array.prototype.filter')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Array.filter")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.forEach()")}}</li> + <li>{{jsxref("Array.prototype.every()")}}</li> + <li>{{jsxref("Array.prototype.some()")}}</li> + <li>{{jsxref("Array.prototype.reduce()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/find/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/find/index.html new file mode 100644 index 0000000000..425901f14d --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/find/index.html @@ -0,0 +1,200 @@ +--- +title: Array.prototype.find() +slug: Web/JavaScript/Reference/Global_Objects/Array/find +tags: + - ECMAScript6 + - JavaScript + - polyfill + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/find +--- +<div>{{JSRef}}</div> + +<p> <code><strong>find()</strong></code> 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 {{jsxref("undefined")}}。</p> + +<p>{{EmbedInteractiveExample("pages/js/array-find.html")}}</p> + +<p>另请参见 {{jsxref("Array.findIndex", "findIndex()")}} 方法,它返回数组中找到的元素的索引,而不是其值。</p> + +<p>如果你需要找到一个元素的位置或者一个元素是否存在于数组中,使用{{jsxref("Array.prototype.indexOf()")}} 或 {{jsxref("Array.prototype.includes()")}}。</p> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox"><code><em>arr</em>.find(<em>callback</em>[, <em>thisArg</em>])</code></pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>在数组每一项上执行的函数,接收 3 个参数: + <dl> + <dt><code>element</code></dt> + <dd>当前遍历到的元素。</dd> + <dt><code>index</code>{{optional_inline}}</dt> + <dd>当前遍历到的索引。</dd> + <dt><code>array</code>{{optional_inline}}</dt> + <dd>数组本身。</dd> + </dl> + </dd> + <dt><code>thisArg</code>{{Optional_inline}}</dt> + <dd>执行回调时用作<code>this</code> 的对象。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>数组中第一个满足所提供测试函数的元素的值,否则返回 {{jsxref("undefined")}}。</p> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>find</code>方法对数组中的每一项元素执行一次 <code>callback</code> 函数,直至有一个 callback 返回 <code>true</code>。当找到了这样一个元素后,该方法会立即返回这个元素的值,否则返回 {{jsxref("undefined")}}。注意 <code>callback </code>函数会为数组中的每个索引调用即从 <code>0 </code>到 <code>length - 1</code>,而不仅仅是那些被赋值的索引,这意味着对于稀疏数组来说,该方法的效率要低于那些只遍历有值的索引的方法。</p> + +<p><code>callback</code>函数带有3个参数:当前元素的值、当前元素的索引,以及数组本身。</p> + +<p>如果提供了 <code>thisArg</code>参数,那么它将作为每次 <code>callback</code>函数执行时的<code>this</code> ,如果未提供,则使用 {{jsxref("undefined")}}。</p> + +<p><code>find</code>方法不会改变数组。</p> + +<p>在第一次调用 <code>callback</code>函数时会确定元素的索引范围,因此在 <code>find</code>方法开始执行之后添加到数组的新元素将不会被 <code>callback</code>函数访问到。如果数组中一个尚未被<code>callback</code>函数访问到的元素的值被<code>callback</code>函数所改变,那么当<code>callback</code>函数访问到它时,它的值是将是根据它在数组中的索引所访问到的当前值。被删除的元素仍旧会被访问到,但是其值已经是undefined了。</p> + +<h2 id="示例">示例</h2> + +<h3 id="用对象的属性查找数组里的对象">用对象的属性查找数组里的对象</h3> + +<pre class="brush: js">var inventory = [ + {name: 'apples', quantity: 2}, + {name: 'bananas', quantity: 0}, + {name: 'cherries', quantity: 5} +]; + +function findCherries(fruit) { + return fruit.name === 'cherries'; +} + +console.log(inventory.find(findCherries)); // { name: 'cherries', quantity: 5 }</pre> + +<h3 id="寻找数组中的质数">寻找数组中的质数</h3> + +<p>下面的例子展示了如何从一个数组中寻找质数(如果找不到质数则返回{{jsxref("undefined")}})</p> + +<pre class="brush: js">function isPrime(element, index, array) { + var start = 2; + while (start <= Math.sqrt(element)) { + if (element % start++ < 1) { + return false; + } + } + return element > 1; +} + +console.log([4, 6, 8, 12].find(isPrime)); // undefined, not found +console.log([4, 5, 8, 12].find(isPrime)); // 5 + +</pre> + +<p>当在回调中删除数组中的一个值时,当访问到这个位置时,其传入的值是 undefined:</p> + +<pre class="brush: js">// Declare array with no element at index 2, 3 and 4 +var a = [0,1,,,,5,6]; + +// Shows all indexes, not just those that have been assigned values +a.find(function(value, index) { + console.log('Visited index ' + index + ' with value ' + value); +}); + +// Shows all indexes, including deleted +a.find(function(value, index) { + + // Delete element 5 on first iteration + if (index == 0) { + console.log('Deleting a[5] with value ' + a[5]); + delete a[5]; // 注:这里只是将a[5]设置为undefined,可以试试用a.pop()删除最后一项,依然会遍历到被删的那一项 + } + // Element 5 is still visited even though deleted + console.log('Visited index ' + index + ' with value ' + value); +});</pre> + +<h2 id="Polyfill" name="Polyfill">Polyfill</h2> + +<p>本方法在ECMAScript 6规范中被加入,可能不存在于某些实现中。你可以通过以下代码来补充 <code>Array.prototype.find()</code>。</p> + +<pre class="brush: js">// https://tc39.github.io/ecma262/#sec-array.prototype.find +if (!Array.prototype.find) { + Object.defineProperty(Array.prototype, 'find', { + value: function(predicate) { + // 1. Let O be ? ToObject(this value). + if (this == null) { + throw new TypeError('"this" is null or not defined'); + } + + var o = Object(this); + + // 2. Let len be ? ToLength(? Get(O, "length")). + var len = o.length >>> 0; + + // 3. If IsCallable(predicate) is false, throw a TypeError exception. + if (typeof predicate !== 'function') { + throw new TypeError('predicate must be a function'); + } + + // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. + var thisArg = arguments[1]; + + // 5. Let k be 0. + var k = 0; + + // 6. Repeat, while k < len + while (k < len) { + // a. Let Pk be ! ToString(k). + // b. Let kValue be ? Get(O, Pk). + // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). + // d. If testResult is true, return kValue. + var kValue = o[k]; + if (predicate.call(thisArg, kValue, k, o)) { + return kValue; + } + // e. Increase k by 1. + k++; + } + + // 7. Return undefined. + return undefined; + } + }); +}</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.find', 'Array.prototype.find')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.find', 'Array.prototype.find')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<p>{{Compat("javascript.builtins.Array.find")}}</p> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.findIndex()")}} – find and return an index</li> + <li>{{jsxref("Array.prototype.includes()")}} – test whether a value exists in the array</li> + <li>{{jsxref("Array.prototype.filter()")}} – find all matching elements</li> + <li>{{jsxref("Array.prototype.every()")}} – test all elements together</li> + <li>{{jsxref("Array.prototype.some()")}} – test at least one element</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/findindex/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/findindex/index.html new file mode 100644 index 0000000000..bd7e039dd0 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/findindex/index.html @@ -0,0 +1,165 @@ +--- +title: Array.prototype.findIndex() +slug: Web/JavaScript/Reference/Global_Objects/Array/findIndex +tags: + - Array + - JavaScript + - Method + - Prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Array/findIndex +--- +<div>{{JSRef}}</div> + +<p><code><strong>findIndex()</strong></code>方法返回数组中满足提供的测试函数的第一个元素的<strong>索引</strong>。若没有找到对应元素则返回-1。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-findindex.html")}}</div> + + + +<p>另请参见 {{jsxref("Array.find", "find()")}} 方法,它返回数组中找到的元素的<strong>值</strong>,而不是其索引。</p> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox notranslate"><code><em>arr</em>.findIndex(<em>callback</em>[, <em>thisArg</em>])</code></pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>针对数组中的每个元素, 都会执行该回调函数, 执行时会自动传入下面三个参数: + <dl> + <dt><code>element</code></dt> + <dd>当前元素。</dd> + <dt><code>index</code></dt> + <dd>当前元素的索引。</dd> + <dt><code>array</code></dt> + <dd>调用<code>findIndex</code>的数组。</dd> + </dl> + </dd> + <dt><code>thisArg</code></dt> + <dd>可选。执行<code>callback</code>时作为<code style="font-size: 14px; line-height: inherit;">this</code>对象<span style="line-height: inherit;">的值.</span></dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p> 数组中通过提供测试函数的第一个元素的<strong>索引</strong>。否则,返回-1</p> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>findIndex</code>方法对数组中的每个数组索引<code>0..length-1</code>(包括)执行一次<code>callback</code>函数,直到找到一个<code>callback</code>函数返回真实值(强制为<code>true</code>)的值。如果找到这样的元素,<code>findIndex</code>会立即返回该元素的索引。如果回调从不返回真值,或者数组的<code>length</code>为0,则<code>findIndex</code>返回-1。 与某些其他数组方法(如Array#some)不同,在稀疏数组中,即使对于数组中不存在的条目的索引也会调用回调函数。</p> + +<p>回调函数调用时有三个参数:元素的值,元素的索引,以及被遍历的数组。</p> + +<p>如果一个 <code>thisArg</code> 参数被提供给 <code>findIndex</code>, 它将会被当作<code>this</code>使用在每次回调函数被调用的时候。如果没有被提供,将会使用{{jsxref("undefined")}}。</p> + +<p><code>findIndex</code>不会修改所调用的数组。</p> + +<p>在第一次调用<code>callback</code>函数时会确定元素的索引范围,因此在<code>findIndex</code>方法开始执行之后添加到数组的新元素将不会被<code>callback</code>函数访问到。如果数组中一个尚未被<code>callback</code>函数访问到的元素的值被<code>callback</code>函数所改变,那么当<code>callback</code>函数访问到它时,它的值是将是根据它在数组中的索引所访问到的当前值。被删除的元素仍然会被访问到。</p> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="Example_Testing_size_of_all_array_elements" name="Example:_Testing_size_of_all_array_elements">查找数组中首个质数元素的索引</h3> + +<p><span style="line-height: inherit;">以下示例查找数组中素数的元素的索引(如果不存在素数,则返回-1)。</span></p> + +<pre class="brush: js notranslate">function isPrime(element, index, array) { + var start = 2; + while (start <= Math.sqrt(element)) { + if (element % start++ < 1) { + return false; + } + } + return element > 1; +} + +console.log([4, 6, 8, 12].findIndex(isPrime)); // -1, not found +console.log([4, 6, 7, 12].findIndex(isPrime)); // 2</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<pre class="brush: js notranslate">// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex +if (!Array.prototype.findIndex) { + Object.defineProperty(Array.prototype, 'findIndex', { + value: function(predicate) { + // 1. Let O be ? ToObject(this value). + if (this == null) { + throw new TypeError('"this" is null or not defined'); + } + + var o = Object(this); + + // 2. Let len be ? ToLength(? Get(O, "length")). + var len = o.length >>> 0; + + // 3. If IsCallable(predicate) is false, throw a TypeError exception. + if (typeof predicate !== 'function') { + throw new TypeError('predicate must be a function'); + } + + // 4. If thisArg was supplied, let T be thisArg; else let T be undefined. + var thisArg = arguments[1]; + + // 5. Let k be 0. + var k = 0; + + // 6. Repeat, while k < len + while (k < len) { + // a. Let Pk be ! ToString(k). + // b. Let kValue be ? Get(O, Pk). + // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)). + // d. If testResult is true, return k. + var kValue = o[k]; + if (predicate.call(thisArg, kValue, k, o)) { + return k; + } + // e. Increase k by 1. + k++; + } + + // 7. Return -1. + return -1; + } + }); +} +</pre> + +<p>如果您需要兼容不支持<code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">Object.defineProperty</a></code>的JavaScript引擎,那么最好不要对<code>Array.prototype</code>方法进行 polyfill ,因为您无法使其成为不可枚举的。</p> + +<p>使用此方法需要注意你是否在uc浏览器环境,如果你的页面在支付宝上使用尤其注意,因为支付宝使用的就是uc浏览器环境.</p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-array.prototype.findindex', 'Array.prototype.findIndex')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.findIndex', 'Array.prototype.findIndex')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容">浏览器兼容</h2> + +<div class="hidden"> +<p>The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p> +</div> + +<p>{{Compat("javascript.builtins.Array.findIndex")}}</p> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.find()")}}</li> + <li>{{jsxref("Array.prototype.indexOf()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/flat/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/flat/index.html new file mode 100644 index 0000000000..5346c65b82 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/flat/index.html @@ -0,0 +1,218 @@ +--- +title: Array.prototype.flat() +slug: Web/JavaScript/Reference/Global_Objects/Array/flat +tags: + - JavaScript + - 原型 + - 参考 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/flat +--- +<div>{{JSRef}}</div> + +<p><code><strong>flat()</strong></code> 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-flat.html")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate"><var>var newArray = arr</var>.flat([<var>depth]</var>)</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>depth</code> {{optional_inline}}</dt> + <dd>指定要提取嵌套数组的结构深度,默认值为 1。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>一个包含将数组与子数组中所有元素的新数组。</p> + +<h2 id="示例">示例</h2> + +<h3 id="扁平化嵌套数组">扁平化嵌套数组</h3> + +<pre class="notranslate">var arr1 = [1, 2, [3, 4]]; +arr1.flat(); +// [1, 2, 3, 4] + +var arr2 = [1, 2, [3, 4, [5, 6]]]; +arr2.flat(); +// [1, 2, 3, 4, [5, 6]] + +var arr3 = [1, 2, [3, 4, [5, 6]]]; +arr3.flat(2); +// [1, 2, 3, 4, 5, 6] + +//使用 Infinity,可展开任意深度的嵌套数组 +<code>var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]]; +arr4.flat(Infinity); +// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]</code></pre> + +<h3 id="扁平化与数组空项">扁平化与数组空项</h3> + +<p><code>flat()</code> 方法会移除数组中的空项:</p> + +<pre class="brush: js notranslate">var arr4 = [1, 2, , 4, 5]; +arr4.flat(); +// [1, 2, 4, 5]</pre> + +<h2 id="替代方案">替代方案</h2> + +<h3 id="使用_reduce_与_concat">使用 <code>reduce</code> 与 <code>concat</code></h3> + +<pre class="notranslate"><code>var arr = [1, 2, [3, 4]]; + +// 展开一层数组 +arr.flat(); +// 等效于 +arr.reduce((acc, val) => acc.concat(val), []); +// [1, 2, 3, 4] + +// 使用扩展运算符 ... +const flattened = arr => [].concat(...arr);</code></pre> + +<h3 class="brush: js" id="reduce_concat_isArray_recursivity">reduce + concat + isArray + recursivity</h3> + +<pre class="brush: js notranslate"><code>// 使用 reduce、concat 和递归展开无限多层嵌套的数组 +var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]]; +</code> +<code class="language-js"><span class="keyword token">function</span> <span class="function token">flatDeep</span><span class="punctuation token">(</span><span class="parameter token">arr<span class="punctuation token">,</span> d <span class="operator token">=</span> <span class="number token">1</span></span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">return</span> d <span class="operator token">></span> <span class="number token">0</span> <span class="operator token">?</span> arr<span class="punctuation token">.</span><span class="function token">reduce</span><span class="punctuation token">(</span><span class="punctuation token">(</span><span class="parameter token">acc<span class="punctuation token">,</span> val</span><span class="punctuation token">)</span> <span class="operator token">=></span> acc<span class="punctuation token">.</span><span class="function token">concat</span><span class="punctuation token">(</span>Array<span class="punctuation token">.</span><span class="function token">isArray</span><span class="punctuation token">(</span>val<span class="punctuation token">)</span> <span class="operator token">?</span> <span class="function token">flatDeep</span><span class="punctuation token">(</span>val<span class="punctuation token">,</span> d <span class="operator token">-</span> <span class="number token">1</span><span class="punctuation token">)</span> <span class="punctuation token">:</span> val<span class="punctuation token">)</span><span class="punctuation token">,</span> <span class="punctuation token">[</span><span class="punctuation token">]</span><span class="punctuation token">)</span> + <span class="punctuation token">:</span> arr<span class="punctuation token">.</span><span class="function token">slice</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span><span class="punctuation token">;</span></code> +<code> +flatDeep(arr1, Infinity); +// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]</code></pre> + +<h3 id="forEachisArraypushrecursivity">forEach+isArray+push+recursivity</h3> + +<pre class="brush: js notranslate">// forEach 遍历数组会自动跳过空元素 +const eachFlat = (arr = [], depth = 1) => { + const result = []; // 缓存递归结果 + // 开始递归 + (function flat(arr, depth) { + // forEach 会自动去除数组空位 + arr.forEach((item) => { + // 控制递归深度 + if (Array.isArray(item) && depth > 0) { + // 递归数组 + flat(item, depth - 1) + } else { + // 缓存元素 + result.push(item) + } + }) + })(arr, depth) + // 返回递归结果 + return result; +} + +// for of 循环不能去除数组空位,需要手动去除 +const forFlat = (arr = [], depth = 1) => { + const result = []; + (function flat(arr, depth) { + for (let item of arr) { + if (Array.isArray(item) && depth > 0) { + flat(item, depth - 1) + } else { + // 去除空元素,添加非undefined元素 + item !== void 0 && result.push(item); + } + } + })(arr, depth) + return result; +} +</pre> + +<h3 id="使用堆栈stack">使用堆栈stack</h3> + +<pre class="notranslate">// 无递归数组扁平化,使用堆栈 +// 注意:深度的控制比较低效,因为需要检查每一个值的深度 +// 也可能在 shift / unshift 上进行 w/o 反转,但是末端的数组 OPs 更快 +var arr1 = [1,2,3,[1,2,3,4, [2,3,4]]]; +function flatten(input) { + const stack = [...input]; + const res = []; + while (stack.length) { + // 使用 pop 从 stack 中取出并移除值 + const next = stack.pop(); + if (Array.isArray(next)) { + // 使用 push 送回内层数组中的元素,不会改动原始输入 + stack.push(...next); + } else { + res.push(next); + } + } + // 反转恢复原数组的顺序 + return res.reverse(); +} +flatten(arr1);// [1, 2, 3, 1, 2, 3, 4, 2, 3, 4]</pre> + +<pre class="notranslate">// 递归版本的反嵌套 +function flatten(array) { + var flattend = []; + (function flat(array) { + array.forEach(function(el) { + if (Array.isArray(el)) flat(el); + else flattend.push(el); + }); + })(array); + return flattend; +}</pre> + +<h3 id="Use_Generator_function">Use <code>Generator</code> function</h3> + +<pre class="notranslate"><code>function* flatten(array) { + for (const item of array) { + if (Array.isArray(item)) { + yield* flatten(item); + } else { + yield item; + } + } +} + +var arr = [1, 2, [3, 4, [5, 6]]]; +const flattened = [...flatten(arr)]; +// [1, 2, 3, 4, 5, 6]</code></pre> + +<p>Please do not add polyfills on this article. For reference, please check: <a href="https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500">https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500</a></p> + +<h2 id="Specifications">Specifications</h2> + +<table> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td><a href="https://www.ecma-international.org/ecma-262/10.0/index.html#sec-array.prototype.flat">ECMAScript 2019</a></td> + <td>Finished</td> + <td>Initial definition</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.flat")}}</p> +</div> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.flatMap()")}}</li> + <li>{{jsxref("Array.prototype.map()")}}</li> + <li>{{jsxref("Array.prototype.reduce()")}}</li> + <li>{{jsxref("Array.prototype.concat()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/flatmap/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/flatmap/index.html new file mode 100644 index 0000000000..9099d44001 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/flatmap/index.html @@ -0,0 +1,149 @@ +--- +title: Array.prototype.flatMap() +slug: Web/JavaScript/Reference/Global_Objects/Array/flatMap +tags: + - Array + - JavaScript + - Method + - Prototype + - Reference +translation_of: Web/JavaScript/Reference/Global_Objects/Array/flatMap +--- +<div>{{JSRef}}</div> + +<p><code><strong>flatMap()</strong></code> 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与 <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a> 连着深度值为1的 <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat">flat</a> 几乎相同,但 <code>flatMap</code> 通常在合并成一种方法的效率稍微高一些。</p> + +<p class="hidden">\{{EmbedInteractiveExample("pages/js/array-flatmap.html")}}</p> + +<p class="hidden">此交互式示例的源代码存储在GitHub存储库中。如果您想要为交互式示例项目做出贡献,请复制https://github.com/mdn/interactive-examples,并向我们发送 pull request。</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate"><var>var new_array = arr</var>.flatMap(function <var>callback(currentValue[, index[, array]]) { + // return element for new_array +}</var>[, <var>thisArg</var>])</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>可以生成一个新数组中的元素的函数,可以传入三个参数: + <dl> + <dt></dt> + <dt><code>currentValue</code></dt> + <dd>当前正在数组中处理的元素</dd> + <dt><code>index</code>{{optional_inline}}</dt> + <dd>可选的。数组中正在处理的当前元素的索引。</dd> + <dt><code>array</code>{{optional_inline}}</dt> + <dd>可选的。被调用的 <code>map</code> 数组</dd> + </dl> + </dd> + <dt><code>thisArg</code>{{optional_inline}}</dt> + <dd>可选的。执行 <code>callback</code> 函数时 使用的<code>this</code> 值。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p> 一个新的数组,其中每个元素都是回调函数的结果,并且结构深度 <code>depth</code> 值为1。</p> + +<h2 id="描述">描述</h2> + +<p>有关回调函数的详细描述,请参见 {{jsxref("Array.prototype.map()")}} 。 <code>flatMap</code> 方法与 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map">map</a></code> 方法和深度depth为1的 <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/flat">flat</a></code> 几乎相同.</p> + +<h2 id="示例">示例</h2> + +<h3 id="map_与_flatMap"><code>map()</code> 与 <code>flatMap()</code></h3> + +<pre class="brush: js notranslate">var arr1 = <span class="js source"><span class="function-call js meta"><span class="js meta"><span class="brace js meta square"><span>[</span></span><span class="constant decimal js numeric"><span>1</span></span><span class="comma delimiter js meta object"><span>,</span></span><span> </span><span class="brace js meta square"><span>2, 3, 4]; + +arr1.map(</span></span></span></span></span>x => [x * 2]<span class="js source"><span class="function-call js meta"><span class="js meta"><span class="brace js meta square"><span>);</span></span></span></span></span> +// [[2], [4], [6], [8]] + +arr1.flatMap(x => [x * 2]<span class="js source"><span class="function-call js meta"><span class="js meta"><span class="brace js meta square"><span>); +// [2, 4, 6, 8]</span></span></span></span></span> + +// <code>only one level is flatt</code><code>ened</code> +arr1.flatMap(x => [[x * 2]]); +// [[2], [4], [6], [8]]</pre> + +<p>虽然上面的代码使用 map 和 flatMap 好像都可以,但这只能展示如何使用 flatMap。</p> + +<p>所以,为了更好的展示 flatMap 的作用,下面我们将包含几句话的数组拆分成单个词组成的新数组。</p> + +<pre class="notranslate"><code>let arr1 = ["it's Sunny in", "", "California"]; + +arr1.map(x => x.split(" ")); +// [["it's","Sunny","in"],[""],["California"]] + +arr1.flatMap(x => x.split(" ")); +// ["it's","Sunny","in", "", "California"]</code></pre> + +<p>注意,输出列表长度可以不同于输入列表长度。</p> + +<h3 id="在一个_map_期间增加或去除一些项">在一个 <code>map()</code> 期间增加或去除一些项</h3> + +<p><code>flatMap</code> 能用于在map期间增删项目(也就是修改items的数量)。换句话说,它允许你遍历很多项使之成为另一些项(靠分别把它们放进去来处理),而不是总是一对一。 从这个意义上讲,它的作用类似于 <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter">filter</a>的对立面。只需返回一个1项元素数组以保留该项,返回一个多元素数组以添加项,或返回一个0项元素数组以删除该项。</p> + +<pre class="notranslate"><code>// Let's say we want to remove all the negative numbers and split the odd numbers into an even number and a 1 +let a = [5, 4, -3, 20, 17, -33, -4, 18] +// |\ \ x | | \ x x | +// [4,1, 4, 20, 16, 1, 18] + +a.flatMap( (n) => + (n < 0) ? [] : + (n % 2 == 0) ? [n] : + [n-1, 1] +) + +// expected output: [4, 1, 4, 20, 16, 1, 18]</code></pre> + +<h2 id="替代方案">替代方案</h2> + +<h3 id="reduce_与_concat"><code>reduce()</code> 与 <code>concat()</code></h3> + +<pre class="notranslate"><code>var arr = [1, 2, 3, 4]; + +arr.flatMap(x => [x, x * 2]); +// is equivalent to +arr.reduce((acc, x) => acc.concat([x, x * 2]), []); +// [1, 2, 2, 4, 3, 6, 4, 8]</code></pre> + +<p>请注意,这是低效的,并且应该避免大型阵列:在每次迭代中,它创建一个必须被垃圾收集的新临时数组,并且它将元素从当前的累加器数组复制到一个新的数组中,而不是将新的元素添加到现有的数组中。</p> + +<div class="hidden"> +<p>Please do not add polyfills on this article. For reference, please check: <a href="https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500">https://discourse.mozilla.org/t/mdn-rfc-001-mdn-wiki-pages-shouldnt-be-a-distributor-of-polyfills/24500</a></p> +</div> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <td>Specification</td> + <td>Status</td> + <td>Comment</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.flatmap', 'Array.prototype.flatMap')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div class="hidden"> +<p>The compatibility table in this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</p> +</div> + +<p>{{Compat("javascript.builtins.Array.flatMap")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.flat()")}}</li> + <li>{{jsxref("Array.prototype.map()")}}</li> + <li>{{jsxref("Array.prototype.reduce()")}}</li> + <li>{{jsxref("Array.prototype.concat()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/foreach/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/foreach/index.html new file mode 100644 index 0000000000..020a7dc3cd --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/foreach/index.html @@ -0,0 +1,384 @@ +--- +title: Array.prototype.forEach() +slug: Web/JavaScript/Reference/Global_Objects/Array/forEach +tags: + - Array + - ECMAScript5 + - JavaScript + - 参考 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/forEach +--- +<div>{{JSRef}}</div> + +<p><code><strong>forEach()</strong></code> 方法对数组的每个元素执行一次给定的函数。</p> + + + +<p>{{EmbedInteractiveExample("pages/js/array-foreach.html")}}</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox"><var>arr</var>.forEach(<var>callback(currentValue [, index [, array]])</var>[, <var>thisArg</var>])</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code><var>callback</var></code></dt> + <dd>为数组中每个元素执行的函数,该函数接收一至三个参数:</dd> + <dd> + <dl> + <dt><code><var>currentValue</var></code></dt> + <dd>数组中正在处理的当前元素。</dd> + <dt><code><var>index</var></code> {{optional_inline}}</dt> + <dd>数组中正在处理的当前元素的索引。</dd> + <dt><code><var>array</var></code> {{optional_inline}}</dt> + <dd><code>forEach()</code> 方法正在操作的数组。</dd> + </dl> + </dd> + <dt><code><var>thisArg</var></code> {{optional_inline}}</dt> + <dd>可选参数。当执行回调函数 <code><var>callback</var></code> 时,用作 <code>this</code> 的值。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>{{jsxref("undefined")}}。</p> + +<h2 id="描述">描述</h2> + +<p><code>forEach()</code> 方法按升序为数组中含有效值的每一项执行一次 <code><var>callback</var></code> 函数,那些已删除或者未初始化的项将被跳过(例如在稀疏数组上)。</p> + +<p>可依次向 <code><var>callback</var></code> 函数传入三个参数:</p> + +<ol> + <li>数组当前项的值</li> + <li>数组当前项的索引</li> + <li>数组对象本身</li> +</ol> + +<p>如果 <code><var>thisArg</var></code> 参数有值,则每次 <code><var>callback</var></code> 函数被调用时,<code>this</code> 都会指向 <code><var>thisArg</var></code> 参数。如果省略了 <code><var>thisArg</var></code> 参数,或者其值为 <code>null</code> 或 <code>undefined</code>,<code>this</code> 则指向全局对象。按照<a href="/zh-CN/docs/Web/JavaScript/Reference/Operators/this">函数观察到 <code>this</code> 的常用规则</a>,<code><var>callback</var></code> 函数最终可观察到 <code>this</code> 值。</p> + +<p><code>forEach()</code> 遍历的范围在第一次调用 <code><var>callback</var></code> 前就会确定。调用 <code>forEach</code> 后添加到数组中的项不会被 <code><var>callback</var></code> 访问到。如果已经存在的值被改变,则传递给 <code><var>callback</var></code> 的值是 <code>forEach()</code> 遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 {{jsxref("Array.prototype.shift()", "shift()")}}),之后的元素将被跳过——<a href="#如果数组在迭代时被修改了,则其他元素会被跳过。">参见下面的示例</a>。</p> + +<p><code>forEach()</code> 为每个数组元素执行一次 <code><var>callback</var></code> 函数;与 {{jsxref("Array.prototype.map()", "map()")}} 或者 {{jsxref("Array.prototype.reduce()", "reduce()")}} 不同的是,它总是返回 {{jsxref("undefined")}} 值,并且不可链式调用。其典型用例是在一个调用链的最后执行副作用(side effects,函数式编程上,指函数进行 返回结果值 以外的操作)。</p> + +<p><code>forEach()</code> 被调用时,不会改变原数组,也就是调用它的数组(尽管 <code><var>callback</var></code> 函数在被调用时可能会改变原数组)。(译注:此处说法可能不够明确,具体可参考EMCA语言规范:'<code>forEach</code> does not directly mutate the object on which it is called but the object may be mutated by the calls to <code><var>callbackfn</var></code>.',即 <code>forEach</code> 不会直接改变调用它的对象,但是那个对象可能会被 <code><var>callback</var></code> 函数改变。)</p> + +<div class="note"> +<p><strong>注意:</strong> 除了抛出异常以外,没有办法中止或跳出 <code>forEach()</code> 循环。如果你需要中止或跳出循环,<code>forEach()</code> 方法不是应当使用的工具。</p> + +<p>若你需要提前终止循环,你可以使用:</p> + +<ul> + <li>一个简单的 <a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for">for</a> 循环</li> + <li><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of">for...of</a> / <a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for...in">for...in</a> 循环</li> + <li>{{jsxref("Array.prototype.every()")}}</li> + <li>{{jsxref("Array.prototype.some()")}}</li> + <li>{{jsxref("Array.prototype.find()")}}</li> + <li>{{jsxref("Array.prototype.findIndex()")}}</li> +</ul> + +<p>这些数组方法则可以对数组元素判断,以便确定是否需要继续遍历:</p> + +<ul> + <li>{{jsxref("Array.prototype.every()", "every()")}}</li> + <li>{{jsxref("Array.prototype.some()", "some()")}}</li> + <li>{{jsxref("Array.prototype.find()", "find()")}}</li> + <li>{{jsxref("Array.prototype.findIndex()", "findIndex()")}}</li> +</ul> + +<p>译者注:只要条件允许,也可以使用 {{jsxref("Array.prototype.filter()", "filter()")}} 提前过滤出需要遍历的部分,再用 <code>forEach()</code> 处理。</p> +</div> + +<h2 id="示例">示例</h2> + +<h3 id="不对未初始化的值进行任何操作(稀疏数组)">不对未初始化的值进行任何操作(稀疏数组)</h3> + +<p>如你所见,<code>3</code> 和 <code>7</code> 之间空缺的数组单元未被 <code>forEach()</code> 调用 <code><var>callback</var></code> 函数,或进行任何其他操作。</p> + +<pre class="brush: js">const arraySparse = [1,3,,7]; +let numCallbackRuns = 0; + +arraySparse.forEach(function(element){ + console.log(element); + numCallbackRuns++; +}); + +console.log("numCallbackRuns: ", numCallbackRuns); + +// 1 +// 3 +// 7 +// numCallbackRuns: 3</pre> + +<h3 id="将_for_循环转换为_forEach">将 for 循环转换为 forEach</h3> + +<pre class="brush:js">const items = ['item1', 'item2', 'item3']; +const copy = []; + +// before +for (let i=0; i<items.length; i++) { + copy.push(items[i]); +} + +// after +items.forEach(function(item){ + copy.push(item); +}); +</pre> + +<h3 id="打印出数组的内容">打印出数组的内容</h3> + +<div class="blockIndicator note"> +<p><strong>注意:</strong>为了在控制台中显示数组的内容,你可以使用 <code><a href="/zh-CN/docs/Web/API/Console/table">console.table()</a></code> 来展示经过格式化的数组。下面的例子则是另一种使用 <code>forEach()</code> 的格式化的方法。</p> +</div> + +<p>下面的代码会为每一个数组元素输出一行记录:</p> + +<pre class="brush:js">function logArrayElements(element, index, array) { + console.log('a[' + index + '] = ' + element); +} + +// 注意索引 2 被跳过了,因为在数组的这个位置没有项 +[2, 5, , 9].forEach(logArrayElements); +// logs: +// a[0] = 2 +// a[1] = 5 +// a[3] = 9 +</pre> + +<h3 id="使用_thisArg">使用 <code><var>thisArg</var></code></h3> + +<p>举个勉强的例子,按照每个数组中的元素值,更新一个对象的属性:</p> + +<pre class="brush:js">function Counter() { + this.sum = 0; + this.count = 0; +} +Counter.prototype.add = function(array) { + array.forEach(function(entry) { + this.sum += entry; + ++this.count; + }, this); + // ^---- Note +}; + +const obj = new Counter(); +obj.add([2, 5, 9]); +obj.count; +// 3 === (1 + 1 + 1) +obj.sum; +// 16 === (2 + 5 + 9) +</pre> + +<p>因为 <code><var>thisArg</var></code> 参数(<code>this</code>)传给了 <code>forEach()</code>,每次调用时,它都被传给 <code><var>callback</var></code> 函数,作为它的 <code>this</code> 值。</p> + +<div> +<div class="note"><strong>注意:</strong>如果使用<a href="/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭头函数表达式</a>来传入函数参数, <code><var>thisArg</var></code> 参数会被忽略,因为箭头函数在词法上绑定了 {{jsxref("Operators/this", "this")}} 值。</div> +</div> + +<h3 id="对象复制器函数">对象复制器函数</h3> + +<p>下面的代码会创建一个给定对象的副本。 创建对象的副本有不同的方法,以下是只是一种方法,并解释了 <code>Array.prototype.forEach()</code> 是如何使用 ECMAScript 5 <code>Object.*</code> 元属性(meta property)函数工作的。</p> + +<pre class="brush: js">function copy(obj) { + const copy = Object.create(Object.getPrototypeOf(obj)); + const propNames = Object.getOwnPropertyNames(obj); + + propNames.forEach(function(name) { + const desc = Object.getOwnPropertyDescriptor(obj, name); + Object.defineProperty(copy, name, desc); + }); + + return copy; +} + +const obj1 = { a: 1, b: 2 }; +const obj2 = copy(obj1); // 现在 obj2 看起来和 obj1 一模一样了 +</pre> + +<h3 id="如果数组在迭代时被修改了,则其他元素会被跳过。">如果数组在迭代时被修改了,则其他元素会被跳过。</h3> + +<p>下面的例子会输出 "one", "two", "four"。当到达包含值 "two" 的项时,整个数组的第一个项被移除了,这导致所有剩下的项上移一个位置。因为元素 "four" 正位于在数组更前的位置,所以 "three" 会被跳过。 <code>forEach()</code> 不会在迭代之前创建数组的副本。</p> + +<pre class="brush:js">var words = ['one', 'two', 'three', 'four']; +words.forEach(function(word) { + console.log(word); + if (word === 'two') { + words.shift(); + } +}); +// one +// two +// four +</pre> + +<h3 id="扁平化数组">扁平化数组</h3> + +<p>下面的示例仅用于学习目的。如果你想使用内置方法来扁平化数组,你可以考虑使用 {{jsxref("Array.prototype.flat()")}}(预计将成为 ES2019 的一部分,并且已在主要浏览器中实现)或参考其 polyfill。</p> + +<pre class="brush: js">/** + * Flattens passed array in one dimensional array + * + * @params {array} arr + * @returns {array} + */ +function flatten(arr) { + const result = []; + + arr.forEach((i) => { + if (Array.isArray(i)) + result.push(...flatten(i)); + else + result.push(i); + }) + + return result; +} + +// Usage +const problem = [1, 2, 3, [4, 5, [6, 7], 8, 9]]; + +flatten(problem); // [1, 2, 3, 4, 5, 6, 7, 8, 9] +</pre> + +<h2 id="针对_promise_或_async_函数的使用备注">针对 promise 或 async 函数的使用备注</h2> + +<p>如果使用 promise 或 async 函数作为 <code>forEach()</code> 等类似方法的 <code><var>callback</var></code> 参数,最好对造成的执行顺序影响多加考虑,否则容易出现错误。</p> + +<pre class="brush: js">let ratings = [5, 4, 5]; + +let sum = 0; + +let sumFunction = async function (a, b) { + return a + b; +} + +ratings.forEach(async function(rating) { + sum = await sumFunction(sum, rating); +}) + +console.log(sum); +// Expected output: 14 +// Actual output: 0 +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p><code>forEach()</code> 是在第五版本里被添加到 ECMA-262 标准的;这样它可能在标准的其他实现中不存在,你可以在你调用 <code>forEach()</code> 之前插入下面的代码,在本地不支持的情况下使用 <code>forEach()</code>。该算法是 ECMA-262 第5版中指定的算法。它假定 {{jsxref("Object")}} 和 {{jsxref("TypeError")}} 拥有它们的初始值,且 <code>callback.call</code> 等价于 {{jsxref("Function.prototype.call()")}}。</p> + +<pre class="brush: js">// Production steps of ECMA-262, Edition 5, 15.4.4.18 +// Reference: http://es5.github.io/#x15.4.4.18 +if (!Array.prototype.forEach) { + + Array.prototype.forEach = function(callback, thisArg) { + + var T, k; + + if (this == null) { + throw new TypeError(' this is null or not defined'); + } + + // 1. Let O be the result of calling toObject() passing the + // |this| value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get() internal + // method of O with the argument "length". + // 3. Let len be toUint32(lenValue). + var len = O.length >>> 0; + + // 4. If isCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== "function") { + throw new TypeError(callback + ' is not a function'); + } + + // 5. If thisArg was supplied, let T be thisArg; else let + // T be undefined. + if (arguments.length > 1) { + T = thisArg; + } + + // 6. Let k be 0 + k = 0; + + // 7. Repeat, while k < len + while (k < len) { + + var kValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty + // internal method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal + // method of O with argument Pk. + kValue = O[k]; + + // ii. Call the Call internal method of callback with T as + // the this value and argument list containing kValue, k, and O. + callback.call(T, kValue, k, O); + } + // d. Increase k by 1. + k++; + } + // 8. return undefined + }; +} +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.foreach', 'Array.prototype.forEach')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.foreach', 'Array.prototype.forEach')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.18', 'Array.prototype.forEach')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.6.</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.forEach")}}</p> +</div> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.find()")}}</li> + <li>{{jsxref("Array.prototype.findIndex()")}}</li> + <li>{{jsxref("Array.prototype.map()")}}</li> + <li>{{jsxref("Array.prototype.filter()")}}</li> + <li>{{jsxref("Array.prototype.every()")}}</li> + <li>{{jsxref("Array.prototype.some()")}}</li> + <li>{{jsxref("Map.prototype.forEach()")}}</li> + <li>{{jsxref("Set.prototype.forEach()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/from/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/from/index.html new file mode 100644 index 0000000000..98a16c1700 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/from/index.html @@ -0,0 +1,258 @@ +--- +title: Array.from() +slug: Web/JavaScript/Reference/Global_Objects/Array/from +tags: + - Array + - ECMAScript 2015 + - JavaScript + - Reference + - arguments + - polyfill + - 参考 + - 数组 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/from +--- +<div>{{JSRef}}</div> + +<p><code><strong>Array.from()</strong></code> 方法从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-from.html")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate">Array.from(<em>arrayLike</em>[, <em>mapFn</em>[, <em>thisArg</em>]]) +</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>arrayLike</code></dt> + <dd>想要转换成数组的伪数组对象或可迭代对象。</dd> + <dt><code>mapFn</code> {{Optional_inline}}</dt> + <dd>如果指定了该参数,新数组中的每个元素会执行该回调函数。</dd> + <dt><code>thisArg</code> {{Optional_inline}}</dt> + <dd>可选参数,执行回调函数 <code>mapFn</code> 时 <code>this</code> 对象。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>一个新的{{jsxref("Array","数组")}}实例。</p> + +<h2 id="描述">描述</h2> + +<p><code>Array.from()</code> 可以通过以下方式来创建数组对象:</p> + +<ul> + <li>伪数组对象(拥有一个 <code>length</code> 属性和若干索引属性的任意对象)</li> + <li><a href="/zh-CN/docs/Web/JavaScript/Guide/iterable">可迭代对象</a>(可以获取对象中的元素,如 Map和 Set 等)</li> +</ul> + +<p><code>Array.from()</code> 方法有一个可选参数 <code>mapFn</code>,让你可以在最后生成的数组上再执行一次 {{jsxref("Array.prototype.map", "map")}} 方法后再返回。也就是说<code> Array.from(obj, mapFn, thisArg) </code>就相当于<code> Array.from(obj).map(mapFn, thisArg),</code> 除非创建的不是可用的中间数组。 这对一些数组的子类<code>,</code>如 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays">typed arrays</a><font face="Consolas, Liberation Mono, Courier, monospace"> 来说很重要,</font> 因为中间数组的值在调用 map() 时需要是适当的类型。</p> + +<p><code>from()</code> 的 <code>length</code> 属性为 1 ,即 <code>Array.from.length === 1</code>。</p> + +<p>在 ES2015 中, <code>Class</code> 语法允许我们为内置类型(比如 <code>Array</code>)和自定义类新建子类(比如叫 <code>SubArray</code>)。这些子类也会继承父类的静态方法,比如 <code>SubArray.from()</code>,调用该方法后会返回子类 <code>SubArray</code> 的一个实例,而不是 <code>Array</code> 的实例。</p> + +<h2 id="示例">示例</h2> + +<h3 id="从_String_生成数组">从 <code>String</code> 生成数组</h3> + +<pre class="brush: js notranslate">Array.from('foo'); +// [ "f", "o", "o" ]</pre> + +<h3 id="从_Set_生成数组">从 <code>Set</code> 生成数组</h3> + +<pre class="brush: js notranslate">const set = new Set(['foo', 'bar', 'baz', 'foo']); +Array.from(set); +// [ "foo", "bar", "baz" ]</pre> + +<h3 id="从_Map_生成数组">从 <code>Map</code> 生成数组</h3> + +<pre class="brush: js notranslate">const map = new Map([[1, 2], [2, 4], [4, 8]]); +Array.from(map); +// [[1, 2], [2, 4], [4, 8]] + +const mapper = new Map([['1', 'a'], ['2', 'b']]); +Array.from(mapper.values()); +// ['a', 'b']; + +Array.from(mapper.keys()); +// ['1', '2']; +</pre> + +<h3 id="从类数组对象(arguments)生成数组">从类数组对象(arguments)生成数组</h3> + +<pre class="brush: js notranslate">function f() { + return Array.from(arguments); +} + +f(1, 2, 3); + +// [ 1, 2, 3 ]</pre> + +<h3 id="在_Array.from_中使用箭头函数">在 <code>Array.from</code> 中使用箭头函数</h3> + +<pre class="brush: js notranslate">// Using an arrow function as the map function to +// manipulate the elements +Array.from([1, 2, 3], x => x + x); +// [2, 4, 6] + + +// Generate a sequence of numbers +// Since the array is initialized with `undefined` on each position, +// the value of `v` below will be `undefined` +Array.from({length: 5}, (v, i) => i); +// [0, 1, 2, 3, 4] +</pre> + +<h3 id="序列生成器指定范围">序列生成器(指定范围)</h3> + +<pre class="brush: js notranslate">// Sequence generator function (commonly referred to as "range", e.g. Clojure, PHP etc) +const range = (start, stop, step) => Array.from({ length: (stop - start) / step + 1}, (_, i) => start + (i * step)); + +// Generate numbers range 0..4 +range(0, 4, 1); +// [0, 1, 2, 3, 4] + +// Generate numbers range 1..10 with step of 2 +range(1, 10, 2); +// [1, 3, 5, 7, 9] + +// Generate the alphabet using Array.from making use of it being ordered as a sequence +range('A'.charCodeAt(0), 'Z'.charCodeAt(0), 1).map(x => String.fromCharCode(x)); +// ["A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z"] +</pre> + +<h3 id="数组去重合并">数组去重合并</h3> + +<pre class="brush: js notranslate">function combine(){ + let arr = [].concat.apply([], arguments); //没有去重复的新数组 + return Array.from(new Set(arr)); +} + +var m = [1, 2, 2], n = [2,3,3]; +console.log(combine(m,n)); // [1, 2, 3]</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p>ECMA-262 第六版标准中添加了 <code>Array.from </code>。有些实现中可能尚未包括在其中。你可以通过在脚本前添加如下内容作为替代方法,以使用未原生支持的 <code>Array.from</code> 方法。该算法按照 ECMA-262 第六版中的规范实现,并假定 <code>Object</code> 和 <code>TypeError</code> 有其本身的值, <code>callback.call</code> 对应 {{jsxref("Function.prototype.call")}} 。此外,鉴于无法使用 Polyfill 实现真正的的迭代器,该实现不支持规范中定义的泛型可迭代元素。</p> + +<pre class="brush: js notranslate">// Production steps of ECMA-262, Edition 6, 22.1.2.1 +if (!Array.from) { + Array.from = (function () { + var toStr = Object.prototype.toString; + var isCallable = function (fn) { + return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; + }; + var toInteger = function (value) { + var number = Number(value); + if (isNaN(number)) { return 0; } + if (number === 0 || !isFinite(number)) { return number; } + return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); + }; + var maxSafeInteger = Math.pow(2, 53) - 1; + var toLength = function (value) { + var len = toInteger(value); + return Math.min(Math.max(len, 0), maxSafeInteger); + }; + + // The length property of the from method is 1. + return function from(arrayLike/*, mapFn, thisArg */) { + // 1. Let C be the this value. + var C = this; + + // 2. Let items be ToObject(arrayLike). + var items = Object(arrayLike); + + // 3. ReturnIfAbrupt(items). + if (arrayLike == null) { + throw new TypeError("Array.from requires an array-like object - not null or undefined"); + } + + // 4. If mapfn is undefined, then let mapping be false. + var mapFn = arguments.length > 1 ? arguments[1] : void undefined; + var T; + if (typeof mapFn !== 'undefined') { + // 5. else + // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. + if (!isCallable(mapFn)) { + throw new TypeError('Array.from: when provided, the second argument must be a function'); + } + + // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 2) { + T = arguments[2]; + } + } + + // 10. Let lenValue be Get(items, "length"). + // 11. Let len be ToLength(lenValue). + var len = toLength(items.length); + + // 13. If IsConstructor(C) is true, then + // 13. a. Let A be the result of calling the [[Construct]] internal method + // of C with an argument list containing the single item len. + // 14. a. Else, Let A be ArrayCreate(len). + var A = isCallable(C) ? Object(new C(len)) : new Array(len); + + // 16. Let k be 0. + var k = 0; + // 17. Repeat, while k < len… (also steps a - h) + var kValue; + while (k < len) { + kValue = items[k]; + if (mapFn) { + A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); + } else { + A[k] = kValue; + } + k += 1; + } + // 18. Let putStatus be Put(A, "length", len, true). + A.length = len; + // 20. Return A. + return A; + }; + }()); +} +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.from', 'Array.from')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-array.from', 'Array.from')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Array.from")}}</p> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array")}}</li> + <li>{{jsxref("Array.prototype.map()")}}</li> + <li>{{jsxref("TypedArray.from()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/includes/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/includes/index.html new file mode 100644 index 0000000000..183d9978b3 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/includes/index.html @@ -0,0 +1,185 @@ +--- +title: Array.prototype.includes() +slug: Web/JavaScript/Reference/Global_Objects/Array/includes +tags: + - Array + - ECMAScript 2016 + - JavaScript + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/includes +--- +<div>{{JSRef}} </div> + +<p><code><strong>includes()</strong></code> 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-includes.html")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre><var>arr</var>.includes(<var>valueToFind[</var>, <var>fromIndex]</var>)</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>valueToFind</code></dt> + <dd> + <p>需要查找的元素值。</p> + + <div class="blockIndicator note"> + <p><strong>Note: </strong>使用<strong> </strong><code>includes()</code>比较字符串和字符时是区分大小写。</p> + </div> + </dd> + <dt><code>fromIndex</code> {{optional_inline}}</dt> + <dd>从<code>fromIndex</code> 索引处开始查找 <code>valueToFind</code>。如果为负值,则按升序从 <code>array.length + fromIndex</code> 的索引开始搜 (即使从末尾开始往前跳 <code>fromIndex</code> 的绝对值个索引,然后往后搜寻)。默认为 0。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>A {{jsxref("Boolean")}} which is <code>true</code> if the value <code>valueToFind</code> is found within the array (or the part of the array indicated by the index <code>fromIndex</code>, if specified). Values of zero are all considered to be equal regardless of sign (that is, -0 is considered to be equal to both 0 and +0), but <code>false</code> is not considered to be the same as 0.</p> + +<p>返回一个布尔值 {{jsxref("Boolean")}} ,如果在数组中找到了(如果传入了 <code>fromIndex</code> ,表示在 <code>fromIndex</code> 指定的索引范围中找到了)则返回 <code>true</code> 。</p> + +<div class="note"> +<p><strong>Note:</strong> Technically speaking, <code>includes()</code> uses the <code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Equality_comparisons_and_sameness#Same-value-zero_equality">sameValueZero</a></code> algorithm to determine whether the given element is found.</p> +</div> + +<h2 id="示例">示例</h2> + +<pre class="brush: js">[1, 2, 3].includes(2); // true +[1, 2, 3].includes(4); // false +[1, 2, 3].includes(3, 3); // false +[1, 2, 3].includes(3, -1); // true +[1, 2, NaN].includes(NaN); // true +</pre> + +<h3 id="fromIndex_大于等于数组长度">fromIndex 大于等于数组长度</h3> + +<p>如果 <code>fromIndex</code> 大于等于数组的长度,则会返回 <code>false</code>,且该数组不会被搜索。</p> + +<pre class="brush: js">var arr = ['a', 'b', 'c']; + +arr.includes('c', 3); // false +arr.includes('c', 100); // false</pre> + +<h3 id="计算出的索引小于_0">计算出的索引小于 0</h3> + +<p>如果 <code>fromIndex </code>为负值,计算出的索引将作为开始搜索<code>searchElement</code>的位置。如果计算出的索引小于 0,则整个数组都会被搜索。</p> + +<pre class="brush: js">// array length is 3 +// fromIndex is -100 +// computed index is 3 + (-100) = -97 + +var arr = ['a', 'b', 'c']; + +arr.includes('a', -100); // true +arr.includes('b', -100); // true +arr.includes('c', -100); // true +arr.includes('a', -2); // false</pre> + +<h3 id="作为通用方法的_includes">作为通用方法的 includes()</h3> + +<p><code>includes()</code> 方法有意设计为通用方法。它不要求<code>this</code>值是数组对象,所以它可以被用于其他类型的对象 (比如类数组对象)。下面的例子展示了 在函数的 <a href="/zh-CN/docs/Web/JavaScript/Reference/Functions/arguments">arguments</a> 对象上调用的 <code>includes()</code> 方法。</p> + +<pre class="brush: js">(function() { + console.log([].includes.call(arguments, 'a')); // true + console.log([].includes.call(arguments, 'd')); // false +})('a','b','c');</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<pre class="brush: js">// https://tc39.github.io/ecma262/#sec-array.prototype.includes +if (!Array.prototype.includes) { + Object.defineProperty(Array.prototype, 'includes', { + value: function(valueToFind, fromIndex) { + + if (this == null) { + throw new TypeError('"this" is null or not defined'); + } + + // 1. Let O be ? ToObject(this value). + var o = Object(this); + + // 2. Let len be ? ToLength(? Get(O, "length")). + var len = o.length >>> 0; + + // 3. If len is 0, return false. + if (len === 0) { + return false; + } + + // 4. Let n be ? ToInteger(fromIndex). + // (If fromIndex is undefined, this step produces the value 0.) + var n = fromIndex | 0; + + // 5. If n ≥ 0, then + // a. Let k be n. + // 6. Else n < 0, + // a. Let k be len + n. + // b. If k < 0, let k be 0. + var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); + + function sameValueZero(x, y) { + return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y)); + } + + // 7. Repeat, while k < len + while (k < len) { + // a. Let elementK be the result of ? Get(O, ! ToString(k)). + // b. If SameValueZero(valueToFind, elementK) is true, return true. + if (sameValueZero(o[k], valueToFind)) { + return true; + } + // c. Increase k by 1. + k++; + } + + // 8. Return false + return false; + } + }); +} + +</pre> + +<p>如果你需要支持那些不支持<code><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">Object.defineProperty</a></code>的废弃JavaScript 引擎,你最好不要 polyfill <code>Array.prototype</code> 方法,因为你不能使它们不可枚举。</p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES7', '#sec-array.prototype.includes', 'Array.prototype.includes')}}</td> + <td>{{Spec2('ES7')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.includes', 'Array.prototype.includes')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Array.includes")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("TypedArray.prototype.includes()")}}</li> + <li>{{jsxref("String.prototype.includes()")}}</li> + <li>{{jsxref("Array.prototype.indexOf()")}}</li> + <li>{{jsxref("Array.prototype.find()")}}</li> + <li>{{jsxref("Array.prototype.findIndex()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/index.html new file mode 100644 index 0000000000..b8c665f147 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/index.html @@ -0,0 +1,445 @@ +--- +title: Array +slug: Web/JavaScript/Reference/Global_Objects/Array +tags: + - JavaScript + - 二维数组 + - 全局对象 + - 参考手册 + - 数组 +translation_of: Web/JavaScript/Reference/Global_Objects/Array +--- +<div>{{JSRef}}</div> + +<div></div> + +<p>JavaScript的 <code><strong>Array</strong></code> 对象是用于构造数组的全局对象,数组是类似于列表的高阶对象。</p> + +<p><strong>创建数组</strong></p> + +<pre class="brush: js">var fruits = ['Apple', 'Banana']; + +console.log(fruits.length); +// 2 +</pre> + +<p><strong>通过索引访问数组元素</strong></p> + +<pre class="brush: js">var first = fruits[0]; +// Apple + +var last = fruits[fruits.length - 1]; +// Banana</pre> + +<p><strong>遍历数组</strong></p> + +<pre class="brush: js">fruits.forEach(function (item, index, array) { + console.log(item, index); +}); +// Apple 0 +// Banana 1</pre> + +<p><strong>添加元素到数组的末尾</strong></p> + +<pre class="brush: js">var newLength = fruits.push('Orange'); +// newLength:3; fruits: ["Apple", "Banana", "Orange"]</pre> + +<p><strong>删除数组末尾的元素</strong></p> + +<pre class="brush: js">var last = fruits.pop(); // remove Orange (from the end) +// last: "Orange"; fruits: ["Apple", "Banana"];</pre> + +<p><strong>删除数组最前面(头部)的元素</strong></p> + +<pre class="brush: js">var first = fruits.shift(); // remove Apple from the front +// first: "Apple"; fruits: ["Banana"];</pre> + +<p><strong>添加元素到数组的头部</strong></p> + +<pre class="brush: js">var newLength = fruits.unshift('Strawberry') // add to the front +// ["Strawberry", "Banana"]; +</pre> + +<p><strong>找出某个元素在数组中的索引</strong></p> + +<pre class="brush: js">fruits.push('Mango'); +// ["Strawberry", "Banana", "Mango"] + +var pos = fruits.indexOf('Banana'); +// 1</pre> + +<p><strong>通过索引删除某个元素</strong></p> + +<pre class="brush: js">var removedItem = fruits.splice(pos, 1); // this is how to remove an item + +// ["Strawberry", "Mango"]</pre> + +<p><strong>从一个索引位置删除多个元素</strong></p> + +<pre class="brush: js">var vegetables = ['Cabbage', 'Turnip', 'Radish', 'Carrot']; +console.log(vegetables); +// ["Cabbage", "Turnip", "Radish", "Carrot"] + +var pos = 1, n = 2; + +var removedItems = vegetables.splice(pos, n); +// this is how to remove items, n defines the number of items to be removed, +// from that position(pos) onward to the end of array. + +console.log(vegetables); +// ["Cabbage", "Carrot"] (the original array is changed) + +console.log(removedItems); +// ["Turnip", "Radish"]</pre> + +<p><strong>复制一个数组</strong></p> + +<pre class="brush: js">var shallowCopy = fruits.slice(); // this is how to make a copy +// ["Strawberry", "Mango"]</pre> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox">[<var>element0</var>, <var>element1</var>, ..., <var>elementN</var>] +new Array(<var>element0</var>, <var>element1</var>[, ...[, <var>elementN</var>]]) +new Array(<var>arrayLength</var>) +</pre> + +<dl> + <dt> + <h3 id="参数">参数</h3> + </dt> + <dt><code>elementN</code></dt> + <dd><code>Array</code> 构造器会根据给定的元素创建一个 JavaScript 数组,但是当仅有一个参数且为数字时除外(详见下面的 <code>arrayLength</code> 参数)。注意,后面这种情况仅适用于用 <code>Array</code> 构造器创建数组,而不适用于用方括号创建的数组字面量。</dd> + <dt><code>arrayLength</code></dt> + <dd>一个范围在 0 到 2<sup>32</sup>-1 之间的整数,此时将返回一个 <code>length</code> 的值等于 <code>arrayLength</code> 的数组对象(言外之意就是该数组此时并没有包含任何实际的元素,不能理所当然地认为它包含 <code>arrayLength</code> 个值为 <code>undefined</code> 的元素)。如果传入的参数不是有效值,则会抛出 {{jsxref("RangeError")}} 异常。</dd> +</dl> + +<h2 id="描述">描述</h2> + +<p>数组是一种类列表对象,它的原型中提供了遍历和修改元素的相关操作。JavaScript 数组的长度和元素类型都是非固定的。因为数组的长度可随时改变,并且其数据在内存中也可以不连续,所以 JavaScript 数组不一定是密集型的,这取决于它的使用方式。一般来说,数组的这些特性会给使用带来方便,但如果这些特性不适用于你的特定使用场景的话,可以考虑使用类型数组 {{jsxref("TypedArray")}}。</p> + +<p>只能用整数作为数组元素的索引,而不能用字符串。后者称为<a href="https://en.wikipedia.org/wiki/Associative_array">关联数组</a>。使用非整数并通过<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects#Objects_and_properties">方括号</a>或<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Property_Accessors">点号</a>来访问或设置数组元素时,所操作的并不是数组列表中的元素,而是数组对象的<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Data_structures#Properties">属性集合</a>上的变量。数组对象的属性和数组元素列表是分开存储的,并且数组的遍历和修改操作也不能作用于这些命名属性。</p> + +<h3 id="访问数组元素">访问数组元素</h3> + +<p>JavaScript 数组的索引是从0开始的,第一个元素的索引为0,最后一个元素的索引等于该数组的长度减1。如果指定的索引是一个无效值,JavaScript 数组并不会报错,而是会返回 <code>undefined</code>。</p> + +<pre class="brush: js language-js">var arr = ['this is the first element', 'this is the second element', 'this is the last element']; +console.log(arr[0]); // 打印 'this is the first element' +console.log(arr[1]); // 打印 'this is the second element' +console.log(arr[arr.length - 1]); // 打印 'this is the last element' +</pre> + +<p>虽然数组元素可以看做是数组对象的属性,就像 <code>toString</code> 一样,但是下面的写法是错误的,运行时会抛出 <code>SyntaxError</code> 异常,而原因则是使用了非法的属性名:</p> + +<pre class="brush: js language-js">console.log(arr.0); // a syntax error +</pre> +<p>并不是 JavaScript 数组有什么特殊之处,而是因为在 JavaScript 中,以数字开头的属性不能用点号引用,必须用方括号。比如,如果一个对象有一个名为 <code>3d</code> 的属性,那么只能用方括号来引用它。下面是具体的例子:</p> + +<pre class="brush: js language-js">var years = [1950, 1960, 1970, 1980, 1990, 2000, 2010]; +console.log(years.0); // 语法错误 +console.log(years[0]); // √ +</pre> +<pre class="brush: js language-js">renderer.3d.setTexture(model, 'character.png'); // 语法错误 +renderer['3d'].setTexture(model, 'character.png'); // √ +</pre> + +<p>注意在 <code>3d</code> 那个例子中,引号是必须的。你也可以将数组的索引用引号引起来,比如 <code>years[2]</code> 可以写成 <code>years['2']</code>。 <code>years[2]</code> 中的 2 会被 JavaScript 解释器通过调用 <code>toString</code> 隐式转换成字符串。正因为这样,<code>'2'</code> 和 <code>'02'</code> 在 <code>years</code> 中所引用的可能是不同位置上的元素。而下面这个例子也可能会打印 <code>true</code>:</p> + +<pre class="brush: js language-js">console.log(years['2'] != years['02']); +</pre> +<p>类似地,如果对象的属性名称是保留字(最好不要这么做!),那么就只能通过字符串的形式用方括号来访问(从 firefox 40.0a2 开始也支持用点号访问了):</p> + +<pre class="brush: js language-js">var promise = { + 'var' : 'text', + 'array': [1, 2, 3, 4] +}; + +console.log(promise['var']); +</pre> + +<h3 id="length_和数字下标之间的关系">length 和数字下标之间的关系</h3> + +<p>JavaScript 数组的 {{jsxref("Array.length", "length")}} 属性和其数字下标之间有着紧密的联系。数组内置的几个方法(例如 {{jsxref("Array.join", "join")}}、{{jsxref("Array.slice", "slice")}}、{{jsxref("Array.indexOf", "indexOf")}} 等)都会考虑 {{jsxref("Array.length", "length")}} 的值。另外还有一些方法(例如 {{jsxref("Array.push", "push")}}、{{jsxref("Array.splice", "splice")}} 等)还会改变 {{jsxref("Array.length", "length")}} 的值。</p> + +<pre class="brush: js language-js">var fruits = []; +fruits.push('banana', 'apple', 'peach'); + +console.log(fruits.length); // 3 +</pre> + +<p>使用一个合法的下标为数组元素赋值,并且该下标超出了当前数组的大小的时候,解释器会同时修改 {{jsxref("Array.length", "length")}} 的值:</p> + +<pre class="brush: js language-js">fruits[5] = 'mango'; +console.log(fruits[5]); // 'mango' +console.log(Object.keys(fruits)); // ['0', '1', '2', '5'] +console.log(fruits.length); // 6 +</pre> + +<p>也可以显式地给 {{jsxref("Array.length", "length")}} 赋一个更大的值:</p> + +<pre class="brush: js language-js">fruits.length = 10; +console.log(Object.keys(fruits)); // ['0', '1', '2', '5'] +console.log(fruits.length); // 10 +</pre> +<p>而为 {{jsxref("Array.length", "length")}} 赋一个更小的值则会删掉一部分元素:</p> + +<pre class="brush: js language-js">fruits.length = 2; +console.log(Object.keys(fruits)); // ['0', '1'] +console.log(fruits.length); // 2</pre> + +<p>这一节的内容在 {{jsxref("Array.length")}} 中有更详细的介绍。</p> +<h3 id="正则匹配结果所返回的数组">正则匹配结果所返回的数组</h3> + +<p>使用正则表达式匹配字符串可以得到一个数组。这个数组中包含本次匹配的相关信息和匹配结果。{{jsxref("RegExp.exec")}}、{{jsxref("String.match")}}、{{jsxref("String.replace")}} 都会返回这样的数组。看下面的例子和例子下面的表格:</p> + +<pre class="brush: js">// 匹配1个 d 后面紧跟着至少1个 b,再后面又跟着1个 d 的子串, +// 并且需要记住子串中匹配到的 b 和最后的 d (通过正则表达式中的分组), +// 同时在匹配时忽略大小写 + +myRe = /d(b+)(d)/i; +myArray = myRe.exec("cdbBdbsbz"); +</pre> + +<p>该正则匹配返回的数组包含以下属性和元素:</p> + +<table class="fullwidth-table"> + <tbody> + <tr> + <td class="header">属性/元素</td> + <td class="header">说明</td> + <td class="header">示例</td> + </tr> + <tr> + <td><code>input</code></td> + <td>只读属性,原始字符串</td> + <td>cdbBdbsbz</td> + </tr> + <tr> + <td><code>index</code></td> + <td>只读属性,匹配到的子串在原始字符串中的索引</td> + <td>1</td> + </tr> + <tr> + <td><code>[0]</code></td> + <td>只读元素,本次匹配到的子串</td> + <td>dbBd</td> + </tr> + <tr> + <td><code>[1], ...[n]</code></td> + <td>只读元素,正则表达式中所指定的分组所匹配到的子串,其数量由正则中的分组数量决定,无最大上限</td> + <td>[1]: bB<br> + [2]: d</td> + </tr> + </tbody> +</table> + +<h2 id="属性">属性</h2> + +<div><code>Array.length</code></div> + +<dl> + <dd><code>Array</code> 构造函数的 length 属性,其值为1(注意该属性为静态属性,不是数组实例的 length 属性)。</dd> + <dt>{{jsxref("Array.@@species", "get Array[@@species]")}}</dt> + <dd>返回 <code>Array</code> 构造函数。</dd> + <dt>{{jsxref("Array.prototype")}}</dt> + <dd>通过数组的原型对象可以为所有数组对象添加属性。</dd> +</dl> + +<h2 id="方法">方法</h2> + +<dl> + <dt>{{jsxref("Array.from()")}}</dt> + <dd>从类数组对象或者可迭代对象中创建一个新的数组实例。</dd> + <dt>{{jsxref("Array.isArray()")}}</dt> + <dd>用来判断某个变量是否是一个数组对象。</dd> + <dt>{{jsxref("Array.of()")}}</dt> + <dd>根据一组参数来创建新的数组实例,支持任意的参数数量和类型。</dd> +</dl> + +<h2 id="数组实例"><font face="Consolas, Liberation Mono, Courier, monospace">数组实例</font></h2> + +<p>所有数组实例都会从 {{jsxref("Array.prototype")}} 继承属性和方法。修改 <code>Array</code> 的原型会影响到所有的数组实例。</p> + +<h3 id="属性_2">属性</h3> + +<div>{{page('/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype', 'Properties')}}</div> + +<h3 id="方法_2">方法</h3> + +<h4 id="修改器方法">修改器方法</h4> + +<p>{{page('zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype', 'Mutator_methods')}}</p> + +<h4 id="访问方法">访问方法</h4> + +<p>{{page('zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype', 'Accessor_methods')}}</p> + +<h4 id="迭代方法">迭代方法</h4> + +<p>{{page('zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/prototype', 'Iteration_methods')}}</p> + +<h2 id="数组泛型方法">数组泛型方法</h2> + +<div class="warning"> +<p><strong>泛型方法是非标准,并且已弃用,有可能不久就会移除。</strong> 需注意的是此方法同时有跨浏览器问题. 但是 <a href="https://github.com/plusdude/array-generics">Github上有可用的shim</a>。</p> +</div> + +<p>有时我们会希望在字符串或其他类数组对象上使用数组所提供的方法(如函数的 {{jsxref("Functions/arguments", "arguments", "", 1)}})。此时你可以把一个字符串作为一个字符数组来看待(也就是说,把非数组以某种方式看成是一个数组)。比如,可以用下面的方法来检查变量 <code>str</code> 中的字符是否都是字母:</p> + +<pre class="brush: js">function isLetter(character) { + return character >= 'a' && character <= 'z'; +} + +if (Array.prototype.every.call(str, isLetter)) { + console.log("The string '" + str + "' contains only letters!"); +}</pre> + +<p>这种方法能够行得通,但不够简洁,JavaScript 1.6 中引入了一个泛型化的简写形式:</p> + +<pre class="brush: js">if (Array.every(str, isLetter)) { + console.log("The string '" + str + "' contains only letters!"); +}</pre> + +<p>{{jsxref("Global_Objects/String", "String")}} 对象也包含一些泛型方法,见: {{jsxref("Global_Objects/String", "Generics", "#String_generic_methods", 1)}}。</p> + +<p>注意,这些并不属于 ECMAScript 标准,也不能在非 Gecko 浏览器中使用。你可以用标准方法 {{jsxref("Array.from()")}} 来替代上面的写法, <code>from</code> 方法可以将一个对象转换为真正的数组(虽然老的浏览器可能不支持):</p> + +<pre class="brush: js"><code>if (Array.from(str).every(isLetter)) { + console.log("The string '" + str + "' contains only letters!"); +}</code></pre> + +<h2 id="示例">示例</h2> + +<h3 id="创建数组">创建数组</h3> + +<p>下面这个例子创建了一个长度为 0 的数组 <code>msgArray</code>,然后给 <code>msgArray[0]</code> 和 <code>msgArray[99]</code> 赋值,从而导致数组长度变为了 100。</p> + +<pre class="brush: js">var msgArray = []; +msgArray[0] = 'Hello'; +msgArray[99] = 'world'; + +if (msgArray.length === 100) { + console.log('The length is 100.'); +}</pre> + +<h3 id="创建二维数组">创建二维数组</h3> + +<p>下面的例子创建了一个代表国际象棋棋盘的二维数组,然后将 (6, 4) 上的 Pawn (卒)拷贝到 (4, 4) 位置,而原本 (6, 4) 位置则被设置为空格。</p> + +<pre class="brush: js">var board = [ + ['R','N','B','Q','K','B','N','R'], + ['P','P','P','P','P','P','P','P'], + [' ',' ',' ',' ',' ',' ',' ',' '], + [' ',' ',' ',' ',' ',' ',' ',' '], + [' ',' ',' ',' ',' ',' ',' ',' '], + [' ',' ',' ',' ',' ',' ',' ',' '], + ['p','p','p','p','p','p','p','p'], + ['r','n','b','q','k','b','n','r'] ]; + +console.log(board.join('\n') + '\n\n'); + +// Move King's Pawn forward 2 +board[4][4] = board[6][4]; +board[6][4] = ' '; +console.log(board.join('\n')); +</pre> + +<p>下面是输出:</p> + +<pre class="brush: js">R,N,B,Q,K,B,N,R +P,P,P,P,P,P,P,P + , , , , , , , + , , , , , , , + , , , , , , , + , , , , , , , +p,p,p,p,p,p,p,p +r,n,b,q,k,b,n,r + +R,N,B,Q,K,B,N,R +P,P,P,P,P,P,P,P + , , , , , , , + , , , , , , , + , , , ,p, , , + , , , , , , , +p,p,p,p, ,p,p,p +r,n,b,q,k,b,n,r +</pre> + +<h3 id="用数组将一组值以表格形式显示">用数组将一组值以表格形式显示</h3> + +<pre class="brush: js"><code>values = []; +for (var x = 0; x < 10; x++){ + values.push([ + 2 ** x, + 2 * x ** 2 + ]) +}; +console.table(values)</code></pre> + +<p>结果为:</p> + +<pre><code>0 1 0 +1 2 2 +2 4 8 +3 8 18 +4 16 32 +5 32 50 +6 64 72 +7 128 98 +8 256 128 +9 512 162</code></pre> + +<p>(第一列为索引)</p> + +<h2 id="规范">规范</h2> + +<table class=" standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">说明</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>初始定义。</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4', 'Array')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>新增方法: {{jsxref("Array.isArray")}}, {{jsxref("Array.prototype.indexOf", "indexOf")}}, {{jsxref("Array.prototype.lastIndexOf", "lastIndexOf")}}, {{jsxref("Array.prototype.every", "every")}}, {{jsxref("Array.prototype.some", "some")}}, {{jsxref("Array.prototype.forEach", "forEach")}}, {{jsxref("Array.prototype.map", "map")}}, {{jsxref("Array.prototype.filter", "filter")}}, {{jsxref("Array.prototype.reduce", "reduce")}}, {{jsxref("Array.prototype.reduceRight", "reduceRight")}}</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array-objects', 'Array')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> + <p>新增方法:{{jsxref("Array.from")}}, {{jsxref("Array.of")}}, {{jsxref("Array.prototype.find", "find")}}, {{jsxref("Array.prototype.findIndex", "findIndex")}}, {{jsxref("Array.prototype.fill", "fill")}}, {{jsxref("Array.prototype.copyWithin", "copyWithin")}}</p> + </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array-objects', 'Array')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> + <p>新增方法:{{jsxref("Array.prototype.includes()")}}</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div> + +<div>{{Compat("javascript.builtins.Array")}}</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects#Indexing_object_properties">JavaScript Guide: “Indexing object properties”</a></li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Predefined_Core_Objects#Array_Object">JavaScript Guide: “Predefined Core Objects: <code>Array</code> Object”</a></li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Array_comprehensions">Array comprehensions</a></li> + <li><a href="https://github.com/plusdude/array-generics">Polyfill for JavaScript 1.8.5 Array Generics and ECMAScript 5 Array Extras</a></li> + <li><a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Typed_arrays">Typed Arrays</a></li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/indexof/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/indexof/index.html new file mode 100644 index 0000000000..c470a8b265 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/indexof/index.html @@ -0,0 +1,197 @@ +--- +title: Array.prototype.indexOf() +slug: Web/JavaScript/Reference/Global_Objects/Array/indexOf +tags: + - JavaScript + - polyfill + - 原型 + - 参考 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/indexOf +--- +<div>{{JSRef}}</div> + +<p><code><strong>indexOf()</strong></code>方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-indexof.html")}}</div> + +<div class="note"> +<p>注意:对于String方法,请参阅 {{jsxref("String.prototype.indexOf()")}}。</p> +</div> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre><var>arr</var>.indexOf(<var>searchElement</var>[, <var>fromIndex</var>])</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>searchElement</code></dt> + <dd>要查找的元素</dd> + <dt><code><var>fromIndex</var></code> {{optional_inline}}</dt> + <dd>开始查找的位置。如果该索引值大于或等于数组长度,意味着不会在数组里查找,返回-1。如果参数中提供的索引值是一个负值,则将其作为数组末尾的一个抵消,即-1表示从最后一个元素开始查找,-2表示从倒数第二个元素开始查找 ,以此类推。 注意:如果参数中提供的索引值是一个负值,并不改变其查找顺序,查找顺序仍然是从前向后查询数组。如果抵消后的索引值仍小于0,则整个数组都将会被查询。其默认值为0.</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>首个被找到的元素在数组中的索引位置; 若没有找到则返回 -1</p> + +<h2 id="描述">描述</h2> + +<p><code>indexOf</code> 使用<a href="/zh-CN/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Using_the_Equality_Operators">strict equality</a> (无论是 ===, 还是 triple-equals操作符都基于同样的方法)进行判断 <code>searchElement与</code>数组中包含的元素之间的关系。</p> + +<h2 id="示例">示例</h2> + +<h3 id="使用indexOf">使用indexOf</h3> + +<p>以下例子使用<code>indexOf方法确定多个值在数组中的位置。</code></p> + +<pre class="brush: js">var array = [2, 5, 9]; +array.indexOf(2); // 0 +array.indexOf(7); // -1 +array.indexOf(9, 2); // 2 +array.indexOf(2, -1); // -1 +array.indexOf(2, -3); // 0 +</pre> + +<h3 id="找出指定元素出现的所有位置">找出指定元素出现的所有位置</h3> + +<pre class="brush: js">var indices = []; +var array = ['a', 'b', 'a', 'c', 'a', 'd']; +var element = 'a'; +var idx = array.indexOf(element); +while (idx != -1) { + indices.push(idx); + idx = array.indexOf(element, idx + 1); +} +console.log(indices); +// [0, 2, 4] +</pre> + +<h3 id="判断一个元素是否在数组里,不在则更新数组">判断一个元素是否在数组里,不在则更新数组</h3> + +<pre class="brush: js">function updateVegetablesCollection (veggies, veggie) { + if (veggies.indexOf(veggie) === -1) { + veggies.push(veggie); + console.log('New veggies collection is : ' + veggies); + } else if (veggies.indexOf(veggie) > -1) { + console.log(veggie + ' already exists in the veggies collection.'); + } +} + +var veggies = ['potato', 'tomato', 'chillies', 'green-pepper']; + +// New veggies collection is : potato,tomato,chillies,green-papper,spinach +updateVegetablesCollection(veggies, 'spinach'); +// spinach already exists in the veggies collection. +updateVegetablesCollection(veggies, 'spinach'); </pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p><code>indexOf</code> 在ECMA-262 标准 的第5版中被加入,但并非所有的浏览器都支持该方法。你可以在编写scripts时,在其开头使用以下代码,它能够允许你在没有本地支持的情况下使用indexOf方法。该算法符合ECMA-262第5版其中一项规定, 即假定 {{jsxref("Global_Objects/TypeError", "TypeError")}}和 {{jsxref("Math.abs")}} 呈现它们原有的值。</p> + +<pre class="brush: js">// Production steps of ECMA-262, Edition 5, 15.4.4.14 +// Reference: http://es5.github.io/#x15.4.4.14 +if (!Array.prototype.indexOf) { + Array.prototype.indexOf = function(searchElement, fromIndex) { + + var k; + + // 1. Let O be the result of calling ToObject passing + // the this value as the argument. + if (this == null) { + throw new TypeError('"this" is null or not defined'); + } + + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get + // internal method of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If len is 0, return -1. + if (len === 0) { + return -1; + } + + // 5. If argument fromIndex was passed let n be + // ToInteger(fromIndex); else let n be 0. + var n = +fromIndex || 0; + + if (Math.abs(n) === Infinity) { + n = 0; + } + + // 6. If n >= len, return -1. + if (n >= len) { + return -1; + } + + // 7. If n >= 0, then Let k be n. + // 8. Else, n<0, Let k be len - abs(n). + // If k is less than 0, then let k be 0. + k = Math.max(n >= 0 ? n : len - Math.abs(n), 0); + + // 9. Repeat, while k < len + while (k < len) { + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the + // HasProperty internal method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + // i. Let elementK be the result of calling the Get + // internal method of O with the argument ToString(k). + // ii. Let same be the result of applying the + // Strict Equality Comparison Algorithm to + // searchElement and elementK. + // iii. If same is true, return k. + if (k in O && O[k] === searchElement) { + return k; + } + k++; + } + return -1; + }; +} +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.14', 'Array.prototype.indexOf')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition.<br> + Implemented in JavaScript 1.6</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.indexof', 'Array.prototype.indexOf')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.indexOf")}}</p> +</div> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.lastIndexOf()")}}</li> + <li>{{jsxref("TypedArray.prototype.indexOf()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/isarray/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/isarray/index.html new file mode 100644 index 0000000000..817312bc5c --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/isarray/index.html @@ -0,0 +1,140 @@ +--- +title: Array.isArray() +slug: Web/JavaScript/Reference/Global_Objects/Array/isArray +tags: + - ECMAScript5 + - JavaScript + - 'brush: js' + - class= + - polyfill + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/isArray +--- +<div>{{JSRef}}</div> + +<p><strong>Array.isArray() </strong>用于确定传递的值是否是一个 {{jsxref("Array")}}。</p> + +<pre class="brush: js">Array.isArray([1, 2, 3]); +// true +Array.isArray({foo: 123}); +// false +Array.isArray("foobar"); +// false +Array.isArray(undefined); +// false +</pre> + +<h2 id="语法">语法</h2> + +<pre>Array.isArray(<var>obj</var>)</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>obj</code></dt> + <dd>需要检测的值。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>如果值是 {{jsxref("Array")}},则为true; 否则为false。</p> + +<h2 id="描述">描述</h2> + +<p>如果对象是 {{jsxref("Array")}} ,则返回true,否则为false。</p> + +<p>有关更多详细信息,请参阅文章<a href="http://web.mit.edu/jwalden/www/isArray.html">严格判定JavaScript对象是否为数组</a>。</p> + +<p>See the article <a href="http://web.mit.edu/jwalden/www/isArray.html">“Determining with absolute accuracy whether or not a JavaScript object is an array”</a> for more details. Given a {{jsxref("TypedArray")}} instance, <code>false</code> is always returned.</p> + +<h2 id="示例">示例</h2> + +<pre class="brush: js">// 下面的函数调用都返回 true +Array.isArray([]); +Array.isArray([1]); +Array.isArray(new Array()); +Array.isArray(new Array('a', 'b', 'c', 'd')) +// 鲜为人知的事实:其实 Array.prototype 也是一个数组。 +Array.isArray(Array.prototype); + +// 下面的函数调用都返回 false +Array.isArray(); +Array.isArray({}); +Array.isArray(null); +Array.isArray(undefined); +Array.isArray(17); +Array.isArray('Array'); +Array.isArray(true); +Array.isArray(false); +Array.isArray(new Uint8Array(32)) +Array.isArray({ __proto__: Array.prototype }); +</pre> + +<h3 id="instanceof_和_isArray"><code>instanceof</code> 和 <code>isArray</code></h3> + +<p>当检测Array实例时, <code>Array.isArray</code> 优于 <code>instanceof</code>,因为Array.isArray能检测<code>iframes</code>.</p> + +<pre><code>var iframe = document.createElement('iframe'); +document.body.appendChild(iframe); +xArray = window.frames[window.frames.length-1].Array; +var arr = new xArray(1,2,3); // [1,2,3] + +// Correctly checking for Array +Array.isArray(arr); // true +// Considered harmful, because doesn't work though iframes +arr instanceof Array; // false</code></pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p>假如不存在 Array.isArray(),则在其他代码之前运行下面的代码将创建该方法。</p> + +<pre class="brush: js">if (!Array.isArray) { + Array.isArray = function(arg) { + return Object.prototype.toString.call(arg) === '[object Array]'; + }; +} +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.3.2', 'Array.isArray')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.8.5.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.isarray', 'Array.isArray')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.isarray', 'Array.isArray')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.isArray")}}</p> +</div> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/join/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/join/index.html new file mode 100644 index 0000000000..c40b87ebed --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/join/index.html @@ -0,0 +1,111 @@ +--- +title: Array.prototype.join() +slug: Web/JavaScript/Reference/Global_Objects/Array/join +tags: + - Array + - Array.prototype.join() + - join() + - separator +translation_of: Web/JavaScript/Reference/Global_Objects/Array/join +--- +<div>{{JSRef}}</div> + +<p><code><strong>join()</strong></code> 方法将一个数组(或一个<a href="/zh-CN//docs/Web/JavaScript/Guide/Indexed_collections#Working_with_array-like_objects">类数组对象</a>)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-join.html")}}</div> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre><var>arr</var>.join([<var>separator</var>])</pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>separator</code> {{optional_inline}}</dt> + <dd>指定一个字符串来分隔数组的每个元素。如果需要,将分隔符转换为字符串。如果缺省该值,数组元素用逗号(<code>,</code>)分隔。如果<code>separator</code>是空字符串(<code>""</code>),则所有元素之间都没有任何字符。</dd> + <dt> + <h3 id="返回值">返回值</h3> + </dt> + <dd>一个所有数组元素连接的字符串。如果 <code>arr.length</code><strong> </strong>为0,则返回空字符串。</dd> +</dl> + +<h2 id="Description" name="Description">描述</h2> + +<p>所有的数组元素被转换成字符串,再用一个分隔符将这些字符串连接起来。</p> + +<div class="blockIndicator warning"> +<p>如果一个元素为 <code>undefined</code> 或 <code>null</code>,它会被转换为空字符串。</p> +</div> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="Example_Joining_an_array_three_different_ways" name="Example:_Joining_an_array_three_different_ways">使用四种不同的分隔符连接数组元素</h3> + +<p>下例首先创建了一个数组 <code>a</code>,包含有三个元素,然后用四种不同的分隔符连接所有数组元素。首先是默认的分隔符逗号,然后是一个逗号加空格,接下来是一个加号前后加空格,最后是一个空字符串。</p> + +<pre class="brush: js">var a = ['Wind', 'Rain', 'Fire']; +var myVar1 = a.join(); // myVar1的值变为"Wind,Rain,Fire" +var myVar2 = a.join(', '); // myVar2的值变为"Wind, Rain, Fire" +var myVar3 = a.join(' + '); // myVar3的值变为"Wind + Rain + Fire" +var myVar4 = a.join(''); // myVar4的值变为"WindRainFire" +</pre> + +<h3 id="连接类数组对象">连接类数组对象</h3> + +<p>下面的示例将连接类数组对象(arguments),通过在<code>Array.prototype.join</code>上调用{{jsxref("Function.prototype.call")}}。</p> + +<pre class="brush: js"><code>function f(a, b, c) { + var s = Array.prototype.join.call(arguments); + console.log(s); // '1,a,true' +} +f(1, 'a', true);</code></pre> + +<h2 id="Specifications" name="Specifications">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.1.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.5', 'Array.prototype.join')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.join', 'Array.prototype.join')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.join', 'Array.prototype.join')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.join")}}</p> +</div> +</div> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li>{{jsxref("String.prototype.split()")}}</li> + <li>{{jsxref("Array.prototype.toString()")}}</li> + <li>{{jsxref("TypedArray.prototype.join()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/keys/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/keys/index.html new file mode 100644 index 0000000000..6da9228ed2 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/keys/index.html @@ -0,0 +1,77 @@ +--- +title: Array.prototype.keys() +slug: Web/JavaScript/Reference/Global_Objects/Array/keys +tags: + - Array + - ECMAScript 2015 + - Iterator + - JavaScript + - Method + - Prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Array/keys +--- +<div>{{JSRef}}</div> + +<p> <code><strong>keys() </strong></code>方法返回一个包含数组中每个索引键的<code><strong>Array Iterator</strong></code>对象。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-keys.html")}}</div> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox"><code><var>arr</var>.keys()</code> +</pre> + +<h3 id="返回值">返回值 </h3> + +<p>一个新的 {{jsxref("Array")}} 迭代器对象。</p> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="索引迭代器会包含那些没有对应元素的索引">索引迭代器会包含那些没有对应元素的索引</h3> + +<pre class="brush: js">var arr = ["a", , "c"]; +var sparseKeys = Object.keys(arr); +var denseKeys = [...arr.keys()]; +console.log(sparseKeys); // ['0', '2'] +console.log(denseKeys); // [0, 1, 2] +</pre> + +<h2 id="Specifications" name="Specifications">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-array.prototype.keys', 'Array.prototype.keys')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.keys', 'Array.prototype.keys')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.keys")}}</p> +</div> +</div> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.values()")}}</li> + <li>{{jsxref("Array.prototype.entries()")}}</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">Iteration protocols</a></li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/lastindexof/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/lastindexof/index.html new file mode 100644 index 0000000000..51cf89a71f --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/lastindexof/index.html @@ -0,0 +1,176 @@ +--- +title: Array.prototype.lastIndexOf() +slug: Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf +translation_of: Web/JavaScript/Reference/Global_Objects/Array/lastIndexOf +--- +<div>{{JSRef("Global_Objects", "Array")}}</div> + +<h2 id="Summary" name="Summary">概述</h2> + +<p><code><strong>lastIndexOf()</strong></code> 方法返回指定元素(也即有效的 JavaScript 值或变量)在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从 <code>fromIndex</code> 处开始。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-lastindexof.html")}}</div> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre><var>arr</var>.lastIndexOf(<var>searchElement[</var>, <var>fromIndex]</var>)</pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>searchElement</code></dt> + <dd>被查找的元素。</dd> + <dt><code>fromIndex</code> {{optional_inline}}</dt> + <dd>从此位置开始逆向查找。默认为数组的长度减 1(<code>arr.length - 1</code>),即整个数组都被查找。如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。</dd> + <dd> + <h3 id="返回值">返回值</h3> + + <p>数组中该元素最后一次出现的索引,如未找到返回-1。</p> + </dd> +</dl> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>lastIndexOf</code> 使用<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Comparison_Operators#Using_the_Equality_Operators">严格相等</a>(strict equality,即 ===)比较 <code>searchElement</code> 和数组中的元素。</p> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="Example_Using_lastIndexOf" name="Example:_Using_lastIndexOf">例子:使用 lastIndexOf</h3> + +<p>下例使用 <code>lastIndexOf</code> 定位数组中的值。</p> + +<pre class="brush: js">var array = [2, 5, 9, 2]; +var index = array.lastIndexOf(2); +// index is 3 +index = array.lastIndexOf(7); +// index is -1 +index = array.lastIndexOf(2, 3); +// index is 3 +index = array.lastIndexOf(2, 2); +// index is 0 +index = array.lastIndexOf(2, -2); +// index is 0 +index = array.lastIndexOf(2, -1); +// index is 3 +</pre> + +<h3 id="Example_Finding_all_the_occurrences_of_an_element" name="Example:_Finding_all_the_occurrences_of_an_element">例子:查找所有元素</h3> + +<p>下例使用 <code>lastIndexOf</code> 查找到一个元素在数组中所有的索引(下标),并使用 {{jsxref("Array.push", "push")}} 将所有添加到另一个数组中。</p> + +<pre class="brush: js">var indices = []; +var array = ['a', 'b', 'a', 'c', 'a', 'd']; +var element = 'a'; +var idx = array.lastIndexOf(element); + +while (idx != -1) { + indices.push(idx); + idx = (idx > 0 ? array.lastIndexOf(element, idx - 1) : -1); +} + +console.log(indices); +// [4, 2, 0]; + +</pre> + +<p>注意,我们要单独处理<code>idx==0</code>时的情况,因为如果是第一个元素,忽略了<code>fromIndex</code>参数则第一个元素总会被查找。这不同于{{jsxref("Array.prototype.indexOf", "indexOf")}}方法</p> + +<p>注:原英文是针对使用三元操作符语句的作用进行说明的:<br> + <code>idx = (idx > 0 ? array.lastIndexOf(element, idx - 1) : -1);</code><br> + <code>idx > 0</code>时,才进入lastIndexOf由后往前移一位进行倒查找;如果<code>idx == 0</code>则直接设置<code>idx = -1</code>,循环<code>while (idx != -1)</code>就结束了。<br> + </p> + +<h2 id="Compatibility" name="Compatibility">兼容旧环境(Polyfill)</h2> + +<p><code>lastIndexOf</code> 在 ECMA-262 标准第 5 版被添加。因此它在不兼容该标准的浏览器中可能不被支持。你可以把下面代码添加到脚本中来使那些没有实现该方法的实现环境支持该方法。该算法是被 ECMA-262 第 5 版指定的。假定 {{jsxref("Global_Objects/Object", "Object")}}、{{jsxref("Global_Objects/TypeError", "TypeError")}}、{{jsxref("Global_Objects/Number", "Number")}}、{{jsxref("Math.floor")}}、{{jsxref("Math.abs")}},以及 {{jsxref("Math.min")}} 拥有其初始值。</p> + +<pre class="brush: js">if (!Array.prototype.lastIndexOf) { + Array.prototype.lastIndexOf = function(searchElement /*, fromIndex*/) { + 'use strict'; + + if (this === void 0 || this === null) { + throw new TypeError(); + } + + var n, k, + t = Object(this), + len = t.length >>> 0; + if (len === 0) { + return -1; + } + + n = len - 1; + if (arguments.length > 1) { + n = Number(arguments[1]); + if (n != n) { + n = 0; + } + else if (n != 0 && n != (1 / 0) && n != -(1 / 0)) { + n = (n > 0 || -1) * Math.floor(Math.abs(n)); + } + } + + for (k = n >= 0 + ? Math.min(n, len - 1) + : len - Math.abs(n); k >= 0; k--) { + if (k in t && t[k] === searchElement) { + return k; + } + } + return -1; + }; +} + +</pre> + +<p>另外,该实现是为了绝对兼容 Firefox 和 the SpiderMonkey JavaScript 引擎中的 <code>lastIndexOf</code>,包括了几种临界情况。如果你要在实际应用中使用该实现,可以忽略这些临界情况,从而简化 <code>fromIndex</code> 的计算。</p> + +<h2 id="Specifications">Specifications</h2> + +<table> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.15', 'Array.prototype.lastIndexOf')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.6.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.lastindexof', 'Array.prototype.lastIndexOf')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.lastindexof', 'Array.prototype.lastIndexOf')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<table class="standard-table"> + <tbody> + <tr> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.lastIndexOf")}}</p> +</div> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.indexOf()")}}</li> + <li>{{jsxref("TypedArray.prototype.lastIndexOf()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/length/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/length/index.html new file mode 100644 index 0000000000..7b126495fb --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/length/index.html @@ -0,0 +1,149 @@ +--- +title: Array.length +slug: Web/JavaScript/Reference/Global_Objects/Array/length +tags: + - JavaScript + - 参考 + - 属性 + - 数组 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/length +--- +<p>{{JSRef}}</p> + +<p><code><strong>length</strong></code> 是<code>Array</code>的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-length.html")}}</div> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>length</code> 属性的值是一个 0 到 2<sup>32</sup>-1 的整数。</p> + +<pre class="brush: js">var namelistA = new Array(4294967296); // 2的32次方 = 4294967296 +var namelistC = new Array(-100) // 负号 + +console.log(namelistA.length); // RangeError: 无效数组长度 +console.log(namelistC.length); // RangeError: 无效数组长度 + + + +var namelistB = []; +namelistB.length = Math.pow(2,32)-1; //set array length less than 2 to the 32nd power +console.log(namelistB.length); + +// 4294967295 +</pre> + +<p>你可以设置 <code>length</code> 属性的值来截断任何数组。当通过改变<code>length</code>属性值来扩展数组时,实际元素的数目将会增加。例如:将一个拥有 2 个元素的数组的 <code>length</code> 属性值设为 3 时,那么这个数组将会包含3个元素,并且,第三个元素的值将会是 <code>undefined</code> 。</p> + +<pre><code>var arr = [1, 2, 3]; +printEntries(arr); + +arr.length = 5; // set array length to 5 while currently 3. +printEntries(arr); + +function printEntries(arr) { + var goNext = true; + var entries = arr.entries(); + while (goNext) { + var result = entries.next(); + if (result.done !== true) { + console.log(result.value[1]); + goNext = true; + } else + goNext = false; + } + console.log('=== printed ==='); +} + +// 1 +// 2 +// 3 +// === printed === +// 1 +// 2 +// 3 +// undefined +// undefined +// === printed ===</code></pre> + +<p>但是, <code>length</code> 属性不一定表示数组中定义值的个数。了解更多:<a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array#Relationship_between_length_and_numerical_properties">长度与数值下标属性之间的关系</a>。</p> + +<p>{{js_property_attributes(1, 0, 0)}}</p> + +<ul> + <li><code>Writable</code> :如果设置为<code>false</code>,该属性值将不能被修改。</li> + <li><code>Configurable</code> :如果设置为<code>false</code>,删除或更改任何属性都将会失败。</li> + <li><code>Enumerable</code> :如果设置为 <code>true</code> ,属性可以通过迭代器<a href="zh-CN/docs/Web/JavaScript/Reference/Statements/for">for</a>或<a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for...in">for...in</a>进行迭代。</li> +</ul> + +<h2 id="Examples" name="Examples">示例 </h2> + +<h3 id="Example:_Iterating_over_an_array" name="Example:_Iterating_over_an_array">遍历数组</h3> + +<p>下面的例子中,通过数组下标遍历数组元素,并把每个元素的值修改为原值的2倍。</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> numbers <span class="operator token">=</span> <span class="punctuation token">[</span><span class="number token">1</span><span class="punctuation token">,</span> <span class="number token">2</span><span class="punctuation token">,</span> <span class="number token">3</span><span class="punctuation token">,</span> <span class="number token">4</span><span class="punctuation token">,</span> <span class="number token">5</span><span class="punctuation token">]</span><span class="punctuation token">;</span> +<span class="keyword token">var</span> length <span class="operator token">=</span> numbers<span class="punctuation token">.</span>length<span class="punctuation token">;</span> +<span class="keyword token">for</span> <span class="punctuation token">(</span><span class="keyword token">var</span> i <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span> i <span class="operator token"><</span> length<span class="punctuation token">;</span> i<span class="operator token">++</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + numbers<span class="punctuation token">[</span>i<span class="punctuation token">]</span> <span class="operator token">*</span><span class="operator token">=</span> <span class="number token">2</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> +<span class="comment token">// 遍历后的结果 [2, 4, 6, 8, 10]</span></code></pre> + +<h3 id="Example:_Shortening_an_array" name="Example:_Shortening_an_array">截断数组</h3> + +<p>下面的例子中,如果数组长度大于 3,则把该数组的长度截断为 3 。</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> numbers <span class="operator token">=</span> <span class="punctuation token">[</span><span class="number token">1</span><span class="punctuation token">,</span> <span class="number token">2</span><span class="punctuation token">,</span> <span class="number token">3</span><span class="punctuation token">,</span> <span class="number token">4</span><span class="punctuation token">,</span> <span class="number token">5</span><span class="punctuation token">]</span><span class="punctuation token">;</span> + +<span class="keyword token">if</span> <span class="punctuation token">(</span>numbers<span class="punctuation token">.</span>length <span class="operator token">></span> <span class="number token">3</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + numbers<span class="punctuation token">.</span>length <span class="operator token">=</span> <span class="number token">3</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> + +console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>numbers<span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// [1, 2, 3]</span> +console<span class="punctuation token">.</span><span class="function token">log</span><span class="punctuation token">(</span>numbers<span class="punctuation token">.</span>length<span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// 3</span></code></pre> + +<h2 id="规范">规范</h2> + +<table> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.5.2', 'Array.length')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-properties-of-array-instances-length', 'Array.length')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-properties-of-array-instances-length', 'Array.length')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.length")}}</p> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/map/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/map/index.html new file mode 100644 index 0000000000..b00ce5df07 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/map/index.html @@ -0,0 +1,343 @@ +--- +title: Array.prototype.map() +slug: Web/JavaScript/Reference/Global_Objects/Array/map +tags: + - Array + - ECMAScript5 + - JavaScript + - Method + - Prototype + - polyfill +translation_of: Web/JavaScript/Reference/Global_Objects/Array/map +--- +<div>{{JSRef}}</div> + +<p><code><strong>map()</strong></code> 方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-map.html")}}</div> + + + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="notranslate"><var>var new_array = arr</var>.map(function <var>callback(currentValue[, index[, array]]) { + // Return element for new_array </var> +<var>}</var>[, <var>thisArg</var>])</pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>生成新数组元素的函数,使用三个参数: + <dl> + <dt><code>currentValue</code></dt> + <dd><code>callback</code> 数组中正在处理的当前元素。</dd> + <dt><code>index</code>{{optional_inline}}</dt> + <dd><code>callback</code> 数组中正在处理的当前元素的索引。</dd> + <dt><code>array</code>{{optional_inline}}</dt> + <dd><code>map</code> 方法调用的数组。</dd> + </dl> + </dd> + <dt><code>thisArg</code>{{optional_inline}}</dt> + <dd>执行 <code>callback</code> 函数时值被用作<code>this</code>。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>一个由原数组每个元素执行回调函数的结果组成的新数组。</p> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>map</code> 方法会给原数组中的每个元素都按顺序调用一次 <code>callback</code> 函数。<code>callback</code> 每次执行后的返回值(包括 {{jsxref("undefined")}})组合起来形成一个新数组。 <code>callback</code> 函数只会在有值的索引上被调用;那些从来没被赋过值或者使用 <code>delete</code> 删除的索引则不会被调用。</p> + +<p>因为<code>map</code>生成一个新数组,当你不打算使用返回的新数组却使用<code>map</code>是违背设计初衷的,请用<code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code>或者<code><a href="/zh-CN/docs/Web/JavaScript/Reference/Statements/for...of">for-of</a></code>替代。你不该使用<code>map</code>: A)你不打算使用返回的新数组,或/且 B) 你没有从回调函数中返回值。</p> + +<p><code>callback</code> 函数会被自动传入三个参数:数组元素,元素索引,原数组本身。</p> + +<p>如果 <code>thisArg</code> 参数提供给<code>map</code>,则会被用作回调函数的<code>this</code>值。否则{{jsxref("undefined")}}会被用作回调函数的<code>this</code>值。<code>this</code>的值最终相对于<code>callback</code>函数的可观察性是依据<a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">the usual rules for determining the this seen by a function</a>决定的</p> + +<p><code>map </code>不修改调用它的原数组本身(当然可以在 <code>callback</code> 执行时改变原数组)</p> + +<p><code>map</code> 方法处理数组元素的范围是在 <code>callback</code> 方法第一次调用之前就已经确定了。调用<code>map</code>方法之后追加的数组元素不会被<code>callback</code>访问。如果存在的数组元素改变了,那么传给<code>callback</code>的值是<code>map</code>访问该元素时的值。在<code>map</code>函数调用后但在访问该元素前,该元素被删除的话,则无法被访问到。</p> + +<p>根据规范中定义的算法,如果被map调用的数组是离散的,新数组将也是离散的保持相同的索引为空。</p> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="Example_Mapping_an_array_of_numbers_to_an_array_of_square_roots" name="Example:_Mapping_an_array_of_numbers_to_an_array_of_square_roots">求数组中每个元素的平方根</h3> + +<p>下面的代码创建了一个新数组,值为原数组中对应数字的平方根。</p> + +<pre class="brush: js notranslate">var numbers = [1, 4, 9]; +var roots = numbers.map(Math.sqrt); +// roots的值为[1, 2, 3], numbers的值仍为[1, 4, 9]</pre> + +<h3 id="使用_map_重新格式化数组中的对象">使用 map 重新格式化数组中的对象</h3> + +<p>以下代码使用一个包含对象的数组来重新创建一个格式化后的数组。</p> + +<pre class="brush: js notranslate">var kvArray = [{key: 1, value: 10}, + {key: 2, value: 20}, + {key: 3, value: 30}]; + +var reformattedArray = kvArray.map(function(obj) { + var rObj = {}; + rObj[obj.key] = obj.value; + return rObj; +}); + +// reformattedArray 数组为: [{1: 10}, {2: 20}, {3: 30}], + +// kvArray 数组未被修改: +// [{key: 1, value: 10}, +// {key: 2, value: 20}, +// {key: 3, value: 30}] +</pre> + +<h3 id="Example_Pluralizing_the_words_.28strings.29_in_an_array" name="Example:_Pluralizing_the_words_.28strings.29_in_an_array">使用一个包含一个参数的函数来mapping(构建)一个数字数组</h3> + +<p>下面的代码表示了当函数需要一个参数时map的工作方式。当map循环遍历原始数组时,这个参数会自动被分配成数组中对应的每个元素。</p> + +<pre class="brush: js notranslate">var numbers = [1, 4, 9]; +var doubles = numbers.map(function(num) { + return num * 2; +}); + +// doubles数组的值为: [2, 8, 18] +// numbers数组未被修改: [1, 4, 9]</pre> + +<h3 id="Example_using_map_generically" name="Example:_using_map_generically">一般的<code>map</code> 方法</h3> + +<p>下面的例子演示如何在一个 {{jsxref("String")}} 上使用 map 方法获取字符串中每个字符所对应的 ASCII 码组成的数组:</p> + +<pre class="brush: js notranslate">var map = Array.prototype.map +var a = map.call("Hello World", function(x) { + return x.charCodeAt(0); +}) +// a的值为[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100] +</pre> + +<h3 id="querySelectorAll_应用"><code>querySelectorAll 应用</code></h3> + +<p>下面代码展示了如何去遍历用 <code>querySelectorAll </code>得到的动态对象集合。在这里,我们获得了文档里所有选中的选项,并将其打印:</p> + +<pre class="brush: js notranslate">var elems = document.querySelectorAll('select option:checked'); +var values = Array.prototype.map.call(elems, function(obj) { + return obj.value; +}); +</pre> + +<h3 id="使用技巧案例">使用技巧案例</h3> + +<p><a class="external" href="http://www.wirfs-brock.com/allzh-cn/posts/166">(原文地址)</a></p> + +<p>通常情况下,<code>map</code> 方法中的 <code>callback</code> 函数只需要接受一个参数,就是正在被遍历的数组元素本身。但这并不意味着 <code>map</code> 只给 <code>callback</code> 传了一个参数。这个思维惯性可能会让我们犯一个很容易犯的错误。</p> + +<p>考虑下例:</p> + +<pre class="notranslate"><code>["1", "2", "3"].map(parseInt);</code></pre> + +<p>我们期望输出 <code>[1, 2, 3]</code>, 而实际结果是 <code>[1, NaN, NaN]</code>.</p> + +<p>parseInt 经常被带着一个参数使用, 但是这里接受两个。第一个参数是一个表达式而第二个是callback function的基, <code>Array.prototype.map</code> 传递3个参数:</p> + +<ul> + <li>the element</li> + <li>the index</li> + <li>the array</li> +</ul> + +<p>第三个参数被parseInt忽视了, <u>but not the second one</u>, 但不是第二个。因此可能出现混淆。下面是迭代步骤的简明示例:</p> + +<pre class="notranslate"><code>// parseInt(string, radix) -> map(parseInt(value, index)) +/* first iteration (index is 0): */ parseInt("1", 0); // 1 +/* second iteration (index is 1): */ parseInt("2", 1); // NaN +/* third iteration (index is 2): */ parseInt("3", 2); // NaN</code></pre> + +<p>下面让我们来讨论解决方案:</p> + +<pre class="notranslate"><code>function returnInt(element) { + return parseInt(element, 10); +} + +['1', '2', '3'].map(returnInt); // [1, 2, 3] +// Actual result is an array of numbers (as expected) + +// Same as above, but using the concise arrow function syntax +['1', '2', '3'].map( str => parseInt(str) ); + +// A simpler way to achieve the above, while avoiding the "gotcha": +['1', '2', '3'].map(Number); // [1, 2, 3] + +// But unlike parseInt(), Number() will also return a float or (resolved) exponential notation: +['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300] +// For comparison, if we use parseInt() on the array above: +['1.1', '2.2e2', '3e300'].map( str => parseInt(str) ); // [1, 2, 3]</code></pre> + +<p>一个map方法调用 parseInt 作为一个参数的等效输出运行如下:</p> + +<pre class="notranslate"><code>var xs = ['10', '10', '10']; + +xs = xs.map(parseInt); + +console.log(xs); // 输出结果为</code>(3) [10, NaN, 2]<code> +// Actual result of 10,NaN,2 may be unexpected based on the above description.</code></pre> + +<h3 id="Mapping_含_undefined的数组">Mapping 含 undefined的数组</h3> + +<p>当返回undefined 或没有返回任何内容时:</p> + +<pre class="notranslate"><code>var numbers = [1, 2, 3, 4]; +var filteredNumbers = numbers.map(function(num, index) { + if(index < 3) { + return num; + } +}); +//index goes from 0,so the filterNumbers are 1,2,3 and undefined. +// filteredNumbers is [1, 2, 3, undefined] +// numbers is still [1, 2, 3, 4]</code></pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p><code>map</code> was added to the ECMA-262 standard in the 5th edition; as such it may not be present in all implementations of the standard. You can work around this by inserting the following code at the beginning of your scripts, allowing use of <code>map</code> in implementations which do not natively support it. This algorithm is exactly the one specified in ECMA-262, 5th edition, assuming {{jsxref("Object")}}, {{jsxref("TypeError")}}, and {{jsxref("Array")}} have their original values and that <code>callback.call</code> evaluates to the original value of <code>{{jsxref("Function.prototype.call")}}</code>.</p> + +<pre class="notranslate"><code>// Production steps of ECMA-262, Edition 5, 15.4.4.19 +// Reference: http://es5.github.io/#x15.4.4.19 +if (!Array.prototype.map) { + + Array.prototype.map = function(callback/*, thisArg*/) { + + var T, A, k; + + if (this == null) { + throw new TypeError('this is null or not defined'); + } + + // 1. Let O be the result of calling ToObject passing the |this| + // value as the argument. + var O = Object(this); + + // 2. Let lenValue be the result of calling the Get internal + // method of O with the argument "length". + // 3. Let len be ToUint32(lenValue). + var len = O.length >>> 0; + + // 4. If IsCallable(callback) is false, throw a TypeError exception. + // See: http://es5.github.com/#x9.11 + if (typeof callback !== 'function') { + throw new TypeError(callback + ' is not a function'); + } + + // 5. If thisArg was supplied, let T be thisArg; else let T be undefined. + if (arguments.length > 1) { + T = arguments[1]; + } + + // 6. Let A be a new array created as if by the expression new Array(len) + // where Array is the standard built-in constructor with that name and + // len is the value of len. + A = new Array(len); + + // 7. Let k be 0 + k = 0; + + // 8. Repeat, while k < len + while (k < len) { + + var kValue, mappedValue; + + // a. Let Pk be ToString(k). + // This is implicit for LHS operands of the in operator + // b. Let kPresent be the result of calling the HasProperty internal + // method of O with argument Pk. + // This step can be combined with c + // c. If kPresent is true, then + if (k in O) { + + // i. Let kValue be the result of calling the Get internal + // method of O with argument Pk. + kValue = O[k]; + + // ii. Let mappedValue be the result of calling the Call internal + // method of callback with T as the this value and argument + // list containing kValue, k, and O. + mappedValue = callback.call(T, kValue, k, O); + + // iii. Call the DefineOwnProperty internal method of A with arguments + // Pk, Property Descriptor + // { Value: mappedValue, + // Writable: true, + // Enumerable: true, + // Configurable: true }, + // and false. + + // In browsers that support Object.defineProperty, use the following: + // Object.defineProperty(A, k, { + // value: mappedValue, + // writable: true, + // enumerable: true, + // configurable: true + // }); + + // For best browser support, use the following: + A[k] = mappedValue; + } + // d. Increase k by 1. + k++; + } + + // 9. return A + return A; + }; +}</code></pre> + +<h2 id="Specifications">Specifications</h2> + +<table> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.19', 'Array.prototype.map')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.6.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.map', 'Array.prototype.map')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.map', 'Array.prototype.map')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<table class="standard-table"> + <tbody> + <tr> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.map")}}</p> +</div> + +<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px;">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.forEach()")}}</li> + <li>{{jsxref("Map")}} object</li> + <li>{{jsxref("Array.from()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/observe/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/observe/index.html new file mode 100644 index 0000000000..7c2dcc8474 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/observe/index.html @@ -0,0 +1,92 @@ +--- +title: Array.observe() +slug: Web/JavaScript/Reference/Global_Objects/Array/observe +tags: + - JavaScript + - 实验性 + - 数组 + - 方法 + - 过时的 +translation_of: Archive/Web/JavaScript/Array.observe +--- +<div>{{JSRef}}{{obsolete_header}}</div> + +<p><strong>Array.observe()</strong> 方法用于异步监视数组发生的变化,类似于针对对象的 {{jsxref("Object.observe()")}} 。当数组的值发生变化时,它按发生顺序提供了一个变化流。与 <code>Object.observe()</code> 类似,它由如下可接受的变化类型列表<code>["add"、"update"、"delete"、"splice"]</code>触发。</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox"><code>Array.observe(<var>arr</var>, <var>callback</var>)</code></pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>arr</code></dt> + <dd>用于被监视的数组</dd> + <dt><code>callback</code></dt> + <dd>每当数组发生变化时,使用如下参数调用该函数: + <dl> + <dt><code>changes</code></dt> + <dd>用于表示变化的对象数组。每个变化对象的属性如下: + <ul> + <li><strong><code>name</code></strong>: 变化的属性名。</li> + <li><strong><code>object</code></strong>: 变化后的数组。</li> + <li><strong><code>type</code></strong>: 用于表示变化类型的字符串。<code>其取值为"add"、</code><code>"update"、</code><code>"delete"</code>或 <code>"splice"</code>之一。</li> + <li><strong><code>oldValue</code></strong>: 仅用于<code>"update"</code>和<code>"delete"类型。变化</code>之前的取值。</li> + <li><strong><code>index</code></strong>: <code>仅用于"splice"类型。</code>变化发生所在索引。</li> + <li><strong><code>removed</code></strong>: 仅用于<code>"splice"类型。</code>被删除元素组成的数组。</li> + <li><strong><code>addedCount</code></strong>: 仅用于<code>"splice"</code>类型。被添加的元素数量。</li> + </ul> + </dd> + </dl> + </dd> +</dl> + +<h2 id="描述">描述</h2> + +<p>每次 arr 发生任何变化时,回调函数将被调用,调用参数为所有变化按发生顺序组成的数组。</p> + +<div class="note"> +<p>通过Array方法如<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/pop"> Array.prototype.pop( )</a> 触发的变化将被报告成"<em>splice</em>"变化,长度不变但索引赋值发生变化的将被报告成"update"变化。</p> +</div> + +<h2 id="示例">示例</h2> + +<h3 id="Example_Logging_different_change_types">Example: Logging different change types</h3> + +<pre class="brush: js">var arr = ['a', 'b', 'c']; + +Array.observe(arr, function(changes) { + console.log(changes); +}); + +arr[1] = 'B'; +// [{type: 'update', object: <arr>, name: '1', oldValue: 'b'}] + +arr[3] = 'd'; +// [{type: 'splice', object: <arr>, index: 3, removed: [], addedCount: 1}] + +arr.splice(1, 2, 'beta', 'gamma', 'delta'); +// [{type: 'splice', object: <arr>, index: 1, removed: ['B', 'c'], addedCount: 3}] +</pre> + +<h2 id="Specifications" name="Specifications">标准规范</h2> + +<p><a href="https://github.com/arv/ecmascript-object-observe">Strawman proposal specification</a>.</p> + +<h2 id="Browser_compatibility" name="Browser_compatibility">浏览器支持</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.observe")}}</p> +</div> +</div> + +<h2 id="See_also" name="See_also">相关内容</h2> + +<ul> + <li>{{jsxref("Array.unobserve()")}} {{experimental_inline}}</li> + <li>{{jsxref("Object.observe()")}} {{experimental_inline}}</li> + <li><a href="https://stackoverflow.com/q/29269057/778272">Under what condition would Array.observe's “add” event trigger?</a></li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/of/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/of/index.html new file mode 100644 index 0000000000..4636c06bdb --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/of/index.html @@ -0,0 +1,99 @@ +--- +title: Array.of() +slug: Web/JavaScript/Reference/Global_Objects/Array/of +tags: + - Array + - Array.of() + - ECMAScript 2015 + - ES 6 + - JavaScript + - polyfill + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/of +--- +<div>{{JSRef}}</div> + +<p><code><strong>Array.of()</strong></code> 方法创建一个具有可变数量参数的新数组实例,而不考虑参数的数量或类型。</p> + +<p> <code><strong>Array.of()</strong></code> 和 <code><strong>Array</strong></code> 构造函数之间的区别在于处理整数参数:<code><strong>Array.of(7)</strong></code><strong> </strong>创建一个具有单个元素 <strong>7</strong> 的数组,而 <strong><code>Array(7)</code> </strong>创建一个长度为7的空数组(<strong>注意:</strong>这是指一个有7个空位(empty)的数组,而不是由7个<code>undefined</code>组成的数组)。</p> + +<pre class="brush: js">Array.of(7); // [7] +Array.of(1, 2, 3); // [1, 2, 3] + +Array(7); // [ , , , , , , ] +Array(1, 2, 3); // [1, 2, 3] +</pre> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox"><code>Array.of(<var>element0</var>[, <var>element1</var>[, ...[, <var>elementN</var>]]])</code></pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt>element<em>N</em></dt> + <dd>任意个参数,将按顺序成为返回数组中的元素。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>新的 {{jsxref("Array")}} 实例。</p> + +<h2 id="描述">描述</h2> + +<p>此函数是ECMAScript 2015标准的一部分。详见 <a href="https://gist.github.com/rwaldron/1074126"><code>Array.of 和</code> <code>Array.from</code> proposal</a> 和 <a href="https://gist.github.com/rwaldron/3186576"><code>Array.of</code> polyfill</a>。</p> + +<h2 id="示例">示例</h2> + +<pre class="brush: js" style="font-size: 14px;"><span style="line-height: 22px;">Array.of(1); // [1] +</span><span style="line-height: 22px;">Array.of(1, 2, 3); // [1, 2, 3]</span> +Array.of(undefined); // [undefined] +</pre> + +<h2 id="Compatibility" name="Compatibility">兼容旧环境</h2> + +<p>如果原生不支持的话,在其他代码之前执行以下代码会创建 <code>Array.of()</code> 。</p> + +<pre class="brush: js" style="font-size: 14px;">if (!Array.of) { + Array.of = function() { + return Array.prototype.slice.call(arguments); + }; +}</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-array.of', 'Array.of')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.of', 'Array.of')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.of")}}</p> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array")}}</li> + <li>{{jsxref("Array.from()")}}</li> + <li>{{jsxref("TypedArray.of()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/pop/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/pop/index.html new file mode 100644 index 0000000000..51fc625019 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/pop/index.html @@ -0,0 +1,101 @@ +--- +title: Array.prototype.pop() +slug: Web/JavaScript/Reference/Global_Objects/Array/pop +tags: + - Array + - Array.prototype.pop() + - ES5 + - ES6 + - Prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Array/pop +--- +<p>{{JSRef}}</p> + +<p><code><strong>pop()</strong></code>方法从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-pop.html")}}</div> + + + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox"><code><em>arr</em>.pop()</code></pre> + +<h3 id="返回值">返回值</h3> + +<p>从数组中删除的元素(当数组为空时返回{{jsxref("undefined")}})。</p> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>pop</code> 方法从一个数组中删除并返回最后一个元素。</p> + +<p><code>pop</code> 方法有意具有通用性。该方法和 {{jsxref("Function.call", "call()")}} 或 {{jsxref("Function.apply", "apply()")}} 一起使用时,可应用在类似数组的对象上。<code>pop</code>方法根据 <code>length</code>属性来确定最后一个元素的位置。如果不包含<code>length</code>属性或<code>length</code>属性不能被转成一个数值,会将<code>length</code>置为0,并返回<code>undefined</code>。</p> + +<p>如果你在一个空数组上调用 pop(),它返回 {{jsxref("undefined")}}。</p> + +<h2 id="Example" name="Example">示例</h2> + +<h3 id="Example:_Removing_the_last_element_of_an_array" name="Example:_Removing_the_last_element_of_an_array">例子: 删除掉数组的最后一个元素</h3> + +<p>下面的代码首先创建了一个拥有四个元素的数组 myFish,然后删除掉它的最后一个元素。</p> + +<pre class="brush:js">let myFish = ["angel", "clown", "mandarin", "surgeon"]; + +let popped = myFish.pop(); + +console.log(myFish); +// ["angel", "clown", "mandarin"] + +console.log(popped); +// surgeon +</pre> + +<h2 id="规范" style="margin-bottom: 20px; line-height: 30px;">规范</h2> + +<table> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Initial definition. Implemented in JavaScript 1.2.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.6', 'Array.prototype.pop')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.pop', 'Array.prototype.pop')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.pop', 'Array.prototype.pop')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.pop")}}</p> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.push()")}}</li> + <li>{{jsxref("Array.prototype.shift()")}}</li> + <li>{{jsxref("Array.prototype.unshift()")}}</li> + <li>{{jsxref("Array.prototype.concat()")}}</li> + <li>{{jsxref("Array.prototype.splice()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/prototype/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/prototype/index.html new file mode 100644 index 0000000000..31d65bf734 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/prototype/index.html @@ -0,0 +1,178 @@ +--- +title: Array.prototype +slug: Web/JavaScript/Reference/Global_Objects/Array/prototype +tags: + - Array.prototype +translation_of: Web/JavaScript/Reference/Global_Objects/Array/prototype +--- +<div>{{JSRef}}</div> + +<p><strong><code>Array.prototype</code></strong> 属性表示 {{jsxref("Array")}} 构造函数的原型,并允许您向所有Array对象添加新的属性和方法。</p> + +<pre class="brush: js">/* +如果JavaScript本身不提供 first() 方法, +添加一个返回数组的第一个元素的新方法。 +*/ + +if(!Array.prototype.first) { + Array.prototype.first = function() { + console.log(`如果JavaScript本身不提供 first() 方法, +添加一个返回数组的第一个元素的新方法。`); + return this[0]; + } +} +</pre> + +<h2 id="Description" name="Description">描述</h2> + +<p>{{jsxref("Array")}}实例继承自 <strong>Array.prototype </strong>。与所有构造函数一样,您可以更改构造函数的原型对象,以对所有 {{jsxref("Array")}} 实例进行更改。例如,可以添加新方法和属性以扩展所有Array对象。这用于 {{Glossary("Polyfill", "polyfilling")}}, 例如。</p> + +<p>鲜为人知的事实:<code>Array.prototype</code> 本身也是一个 {{jsxref("Array")}}。</p> + +<pre class="brush: js">Array.isArray(Array.prototype); +// true +</pre> + +<p>{{js_property_attributes(0, 0, 0)}}</p> + +<h2 id="Properties" name="Properties">属性</h2> + +<dl> + <dt><code>Array.prototype.constructor</code></dt> + <dd>所有的数组实例都继承了这个属性,它的值就是 {{jsxref("Array")}},表明了所有的数组都是由 {{jsxref("Array")}} 构造出来的。</dd> + <dt>{{jsxref("Array.prototype.length")}}</dt> + <dd>上面说了,因为 <code>Array.prototype</code> 也是个数组,所以它也有 <code>length</code> 属性,这个值为 <code>0</code>,因为它是个空数组。</dd> +</dl> + +<h2 id="Methods" name="Methods">方法</h2> + +<h3 id="Mutator_methods" name="Mutator_methods">会改变自身的方法</h3> + +<p>下面的这些方法会改变调用它们的对象自身的值:</p> + +<dl> + <dt>{{jsxref("Array.prototype.copyWithin()")}} {{experimental_inline}}</dt> + <dd>在数组内部,将一段元素序列拷贝到另一段元素序列上,覆盖原有的值。</dd> + <dt>{{jsxref("Array.prototype.fill()")}} {{experimental_inline}}</dt> + <dd>将数组中指定区间的所有元素的值,都替换成某个固定的值。</dd> + <dt>{{jsxref("Array.prototype.pop()")}}</dt> + <dd>删除数组的最后一个元素,并返回这个元素。</dd> + <dt>{{jsxref("Array.prototype.push()")}}</dt> + <dd>在数组的末尾增加一个或多个元素,并返回数组的新长度。</dd> + <dt>{{jsxref("Array.prototype.reverse()")}}</dt> + <dd>颠倒数组中元素的排列顺序,即原先的第一个变为最后一个,原先的最后一个变为第一个。</dd> + <dt>{{jsxref("Array.prototype.shift()")}}</dt> + <dd>删除数组的第一个元素,并返回这个元素。</dd> + <dt>{{jsxref("Array.prototype.sort()")}}</dt> + <dd>对数组元素进行排序,并返回当前数组。</dd> + <dt>{{jsxref("Array.prototype.splice()")}}</dt> + <dd>在任意的位置给数组添加或删除任意个元素。</dd> + <dt>{{jsxref("Array.prototype.unshift()")}}</dt> + <dd>在数组的开头增加一个或多个元素,并返回数组的新长度。</dd> +</dl> + +<h3 id="Accessor_methods" name="Accessor_methods">不会改变自身的方法</h3> + +<p>下面的这些方法绝对不会改变调用它们的对象的值,只会返回一个新的数组或者返回一个其它的期望值。</p> + +<dl> + <dt>{{jsxref("Array.prototype.concat()")}}</dt> + <dd>返回一个由当前数组和其它若干个数组或者若干个非数组值组合而成的新数组。</dd> + <dt>{{jsxref("Array.prototype.includes()")}} {{experimental_inline}}</dt> + <dd>判断当前数组是否包含某指定的值,如果是返回 <code>true</code>,否则返回 <code>false</code>。</dd> + <dt>{{jsxref("Array.prototype.join()")}}</dt> + <dd>连接所有数组元素组成一个字符串。</dd> + <dt>{{jsxref("Array.prototype.slice()")}}</dt> + <dd>抽取当前数组中的一段元素组合成一个新数组。</dd> + <dt>{{jsxref("Array.prototype.toSource()")}} {{non-standard_inline}}</dt> + <dd>返回一个表示当前数组字面量的字符串。遮蔽了原型链上的 {{jsxref("Object.prototype.toSource()")}} 方法。</dd> + <dt>{{jsxref("Array.prototype.toString()")}}</dt> + <dd>返回一个由所有数组元素组合而成的字符串。遮蔽了原型链上的 {{jsxref("Object.prototype.toString()")}} 方法。</dd> + <dt>{{jsxref("Array.prototype.toLocaleString()")}}</dt> + <dd>返回一个由所有数组元素组合而成的本地化后的字符串。遮蔽了原型链上的 {{jsxref("Object.prototype.toLocaleString()")}} 方法。</dd> + <dt>{{jsxref("Array.prototype.indexOf()")}}</dt> + <dd>返回数组中第一个与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。</dd> + <dt>{{jsxref("Array.prototype.lastIndexOf()")}}</dt> + <dd>返回数组中最后一个(从右边数第一个)与指定值相等的元素的索引,如果找不到这样的元素,则返回 -1。</dd> +</dl> + +<h3 id="Iteration_methods" name="Iteration_methods">遍历方法</h3> + +<p>在下面的众多遍历方法中,有很多方法都需要指定一个回调函数作为参数。在每一个数组元素都分别执行完回调函数之前,数组的length属性会被缓存在某个地方,所以,如果你在回调函数中为当前数组添加了新的元素,那么那些新添加的元素是不会被遍历到的。此外,如果在回调函数中对当前数组进行了其它修改,比如改变某个元素的值或者删掉某个元素,那么随后的遍历操作可能会受到未预期的影响。总之,不要尝试在遍历过程中对原数组进行任何修改,虽然规范对这样的操作进行了详细的定义,但为了可读性和可维护性,请不要这样做。</p> + +<dl> + <dt>{{jsxref("Array.prototype.forEach()")}}</dt> + <dd>为数组中的每个元素执行一次回调函数。</dd> + <dt>{{jsxref("Array.prototype.entries()")}} {{experimental_inline}}</dt> + <dd>返回一个数组迭代器对象,该迭代器会包含所有数组元素的键值对。</dd> + <dt>{{jsxref("Array.prototype.every()")}}</dt> + <dd>如果数组中的每个元素都满足测试函数,则返回 <code>true</code>,否则返回 <code>false。</code></dd> + <dt>{{jsxref("Array.prototype.some()")}}</dt> + <dd>如果数组中至少有一个元素满足测试函数,则返回 true,否则返回 false。</dd> + <dt>{{jsxref("Array.prototype.filter()")}}</dt> + <dd>将所有在过滤函数中返回 <code>true</code> 的数组元素放进一个新数组中并返回。</dd> + <dt>{{jsxref("Array.prototype.find()")}} {{experimental_inline}}</dt> + <dd>找到第一个满足测试函数的元素并返回那个元素的值,如果找不到,则返回 <code>undefined</code>。</dd> + <dt>{{jsxref("Array.prototype.findIndex()")}} {{experimental_inline}}</dt> + <dd>找到第一个满足测试函数的元素并返回那个元素的索引,如果找不到,则返回 <code>-1</code>。</dd> + <dt>{{jsxref("Array.prototype.keys()")}} {{experimental_inline}}</dt> + <dd>返回一个数组迭代器对象,该迭代器会包含所有数组元素的键。</dd> + <dt>{{jsxref("Array.prototype.map()")}}</dt> + <dd>返回一个由回调函数的返回值组成的新数组。</dd> + <dt>{{jsxref("Array.prototype.reduce()")}}</dt> + <dd>从左到右为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。</dd> + <dt>{{jsxref("Array.prototype.reduceRight()")}}</dt> + <dd>从右到左为每个数组元素执行一次回调函数,并把上次回调函数的返回值放在一个暂存器中传给下次回调函数,并返回最后一次回调函数的返回值。</dd> + <dt>{{jsxref("Array.prototype.values()")}} {{experimental_inline}}</dt> + <dd>返回一个数组迭代器对象,该迭代器会包含所有数组元素的值。</dd> + <dt>{{jsxref("Array.prototype.@@iterator()", "Array.prototype[@@iterator]()")}} {{experimental_inline}}</dt> + <dd>和上面的 <code>values() 方法是同一个函数。</code></dd> +</dl> + +<h3 id="Generic_methods" name="Generic_methods">通用方法</h3> + +<p>在 JavaScript 中,很多的数组方法被故意设计成是通用的。也就是说,那些看起来像是数组的对象(类数组对象),即拥有一个 <code>length</code> 属性,以及对应的索引属性(也就是数字类型的属性,比如 <code>obj[5]</code>)的非数组对象也是可以调用那些数组方法的。其中一些数组方法,比如说 {{jsxref("Array.join", "join")}} 方法,它们只会单纯的读取当前对象的 <code>length</code> 属性和索引属性的值,并不会尝试去改变这些属性的值。而另外一些数组方法,比如说 {{jsxref("Array.reverse", "reverse")}} 方法,它们会尝试修改那些属性的值,因此,如果当前对象是个 {{jsxref("String")}} 对象,那么这些方法在执行时就会报错,因为字符串对象的 <code>length</code> 属性和索引属性都是只读的。</p> + +<h2 id="Specifications" name="Specifications">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.3.1', 'Array.prototype')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype', 'Array.prototype')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.prototype")}}</p> +</div> +</div> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li>{{jsxref("Array")}}</li> + <li>{{jsxref("Function.prototype")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/push/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/push/index.html new file mode 100644 index 0000000000..3be7c12520 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/push/index.html @@ -0,0 +1,149 @@ +--- +title: Array.prototype.push() +slug: Web/JavaScript/Reference/Global_Objects/Array/push +tags: + - Array + - Array.prototype.push() + - JavaScript + - Method + - Prototype + - 参考 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/push +--- +<div>{{JSRef}}</div> + +<p><code><strong>push()</strong></code> 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-push.html")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox">arr.push(element1, ..., elementN) +</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>element<em>N</em></code></dt> + <dd>被添加到数组末尾的元素。</dd> +</dl> + +<h3 id="返回值" style="line-height: 24px;">返回值</h3> + +<p>当调用该方法时,新的 {{jsxref("Array.length", "length")}} 属性值将被返回。</p> + +<h2 id="Description" name="Description" style="margin-bottom: 20px; line-height: 30px;">描述</h2> + +<p>push方法将值追加到数组中。</p> + +<p><code>push</code> 方法具有通用性。该方法和 {{jsxref("Function.call", "call()")}} 或 {{jsxref("Function.apply", "apply()")}} 一起使用时,可应用在类似数组的对象上。<code>push</code> 方法根据 <code>length</code> 属性来决定从哪里开始插入给定的值。如果 <code>length</code> 不能被转成一个数值,则插入的元素索引为 0,包括 <code>length</code> 不存在时。当 <code>length</code> 不存在时,将会创建它。</p> + +<p>唯一的原生类数组(array-like)对象是 {{jsxref("Global_Objects/String", "Strings")}},尽管如此,它们并不适用该方法,因为字符串是不可改变的。</p> + +<h2 id="示例">示例</h2> + +<h3 id="添加元素到数组">添加元素到数组</h3> + +<p>下面的代码创建了 <code>sports</code> 数组,包含两个元素,然后又把两个元素添加给它。<code>total</code> 变量为数组的新长度值。</p> + +<pre class="brush: js">var sports = ["soccer", "baseball"]; +var total = sports.push("football", "swimming"); + +console.log(sports); +// ["soccer", "baseball", "football", "swimming"] + +console.log(total); +// 4</pre> + +<h3 id="合并两个数组">合并两个数组</h3> + +<p>该示例使用 {{jsxref("Function.apply", "apply()")}} 添加第二个数组的所有元素。</p> + +<p>注意当第二个数组(如示例中的moreVegs)太大时不要使用这个方法来合并数组,因为事实上一个函数能够接受的参数个数是有限制的。具体可以参考 {{jsxref("Function.apply", "apply()")}} 。</p> + +<pre class="brush: js">var vegetables = ['parsnip', 'potato']; +var moreVegs = ['celery', 'beetroot']; + +// 将第二个数组融合进第一个数组 +// 相当于 vegetables.push('celery', 'beetroot'); +Array.prototype.push.apply(vegetables, moreVegs); + +console.log(vegetables); +// ['parsnip', 'potato', 'celery', 'beetroot']</pre> + +<h3 id="像数组一样使用对象">像数组一样使用对象</h3> + +<p>如上所述,push 是特意设计为通用的,我们可以使用它来获得便利。正如下面的例子所示,Array.prototype.push 可以在一个对象上工作。 注意,我们没有创建一个数组来存储对象的集合。 相反,我们将该集合存储在对象本身上,并使用在 Array.prototype.push 上使用的 <code>call</code> 来调用该方法,使其认为我们正在处理数组,而它只是像平常一样运作,这要感谢 JavaScript 允许我们建立任意的执行上下文。</p> + +<pre class="brush: js">var obj = { + length: 0, + + addElem: function addElem (elem) { + // obj.length is automatically incremented + // every time an element is added. + [].push.call(this, elem); + } +}; + +// Let's add some empty objects just to illustrate. +obj.addElem({}); +obj.addElem({}); +console.log(obj.length); +// → 2</pre> + +<p>注意,尽管 obj 不是数组,但是 push 方法成功地使 obj 的 length 属性增长了,就像我们处理一个实际的数组一样。</p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Initial definition. Implemented in JavaScript 1.2.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.7', 'Array.prototype.push')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.push', 'Array.prototype.push')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.push', 'Array.prototype.push')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.push")}}</p> +</div> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.pop()")}}</li> + <li>{{jsxref("Array.prototype.shift()")}}</li> + <li>{{jsxref("Array.prototype.unshift()")}}</li> + <li>{{jsxref("Array.prototype.concat()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/reduce/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/reduce/index.html new file mode 100644 index 0000000000..75edc90a73 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/reduce/index.html @@ -0,0 +1,688 @@ +--- +title: Array.prototype.reduce() +slug: Web/JavaScript/Reference/Global_Objects/Array/Reduce +tags: + - Array + - ECMAScript 5 + - JavaScript + - Method + - Prototype + - Reduce + - Reference +translation_of: Web/JavaScript/Reference/Global_Objects/Array/Reduce +--- +<p>{{JSRef}}</p> + +<p><code><strong>reduce()</strong></code> 方法对数组中的每个元素执行一个由您提供的<strong>reducer</strong>函数(升序执行),将其结果汇总为单个返回值。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-reduce.html")}}</div> + +<div class="hidden"> +<p>The source for this interactive example is stored in a GitHub repository. If you'd like to contribute to the interactive examples project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request. </p> +</div> + +<div> +<p><strong>reducer</strong> 函数接收4个参数:</p> + +<ol> + <li>Accumulator (acc) (累计器)</li> + <li>Current Value (cur) (当前值)</li> + <li>Current Index (idx) (当前索引)</li> + <li>Source Array (src) (源数组)</li> +</ol> + +<p>您的 <strong>reducer</strong> 函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。</p> +</div> + +<h2 id="语法">语法</h2> + +<pre class="notranslate"><var>arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])</var></pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>执行数组中每个值 (如果没有提供 <code>initialValue则第一个值除外</code>)的函数,包含四个参数:</dd> + <dd> + <dl> + </dl> + <strong><code>accumulator</code></strong> + + <dl> + <dd> + <p>累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或<code>initialValue</code>(见于下方)。</p> + </dd> + <dt><code>currentValue</code></dt> + <dd>数组中正在处理的元素。</dd> + <dt><code>index</code> {{optional_inline}}</dt> + <dd>数组中正在处理的当前元素的索引。 如果提供了<code>initialValue</code>,则起始索引号为0,否则从索引1起始。</dd> + <dt><code>array</code>{{optional_inline}}</dt> + <dd>调用<code>reduce()</code>的数组</dd> + </dl> + </dd> + <dt><code>initialValue</code>{{optional_inline}}</dt> + <dd>作为第一次调用 <code>callback</code>函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>函数累计处理的结果</p> + +<h2 id="描述">描述</h2> + +<p><code>reduce</code>为数组中的每一个元素依次执行<code>callback</code>函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:</p> + +<ul> + <li><code>accumulator 累计器</code></li> + <li><code>currentValue 当前值</code></li> + <li><code>currentIndex 当前索引</code></li> + <li><code>array 数组</code></li> +</ul> + +<p>回调函数第一次执行时,<code>accumulator</code><span style="line-height: 1.5;"> 和</span><code>currentValue</code>的取值有两种情况:如果调用<code>reduce()</code>时提供了<code>initialValue</code>,<code>accumulator</code>取值为<code>initialValue</code>,<code>currentValue</code>取数组中的第一个值;如果没有提供 <code>initialValue</code>,那么<code>accumulator</code>取数组中的第一个值,<code>currentValue</code>取数组中的第二个值。</p> + +<div class="note"> +<p><strong>注意:</strong>如果没有提供<code>initialValue</code>,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供<code>initialValue</code>,从索引0开始。</p> +</div> + +<p>如果数组为空且没有提供<code>initialValue</code>,会抛出{{jsxref("TypeError")}} 。如果数组仅有一个元素(无论位置如何)并且没有提供<code>initialValue</code>, 或者有提供<code>initialValue</code>但是数组为空,那么此唯一值将被返回并且<code>callback</code>不会被执行。</p> + +<p>提供初始值通常更安全,正如下面的例子,如果没有提供<code>initialValue</code>,则可能有四种输出:</p> + +<pre class="brush: js notranslate">var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x ); +var maxCallback2 = ( max, cur ) => Math.max( max, cur ); + +// reduce() 没有初始值 +[ { x: 2 }, { x: 22 }, { x: 42 } ].reduce( maxCallback ); // NaN +[ { x: 2 }, { x: 22 } ].reduce( maxCallback ); // 22 +[ { x: 2 } ].reduce( maxCallback ); // { x: 2 } +[ ].reduce( maxCallback ); // TypeError + +// map/reduce; 这是更好的方案,即使传入空数组或更大数组也可正常执行 +[ { x: 22 }, { x: 42 } ].map( el => el.x ) + .reduce( maxCallback2, -Infinity ); +</pre> + +<h3 id="reduce_如何运行">reduce() 如何运行</h3> + +<p>假如运行下段<code>reduce()</code>代码:</p> + +<pre class="brush:js notranslate">[0, 1, 2, 3, 4].reduce(function(accumulator, currentValue, currentIndex, array){ + return accumulator + currentValue; +}); +</pre> + +<p>callback 被调用四次,每次调用的参数和返回值如下表:</p> + +<table> + <thead> + <tr> + <th scope="col"><code>callback</code></th> + <th scope="col"><code>accumulator</code></th> + <th scope="col"><code>currentValue</code></th> + <th scope="col"><code>currentIndex</code></th> + <th scope="col"><code>array</code></th> + <th scope="col">return value</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">first call</th> + <td><code>0</code></td> + <td><code>1</code></td> + <td><code>1</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>1</code></td> + </tr> + <tr> + <th scope="row">second call</th> + <td><code>1</code></td> + <td><code>2</code></td> + <td><code>2</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>3</code></td> + </tr> + <tr> + <th scope="row">third call</th> + <td><code>3</code></td> + <td><code>3</code></td> + <td><code>3</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>6</code></td> + </tr> + <tr> + <th scope="row">fourth call</th> + <td><code>6</code></td> + <td><code>4</code></td> + <td><code>4</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>10</code></td> + </tr> + </tbody> +</table> + +<table style="width: 100%;"> + <tbody> + <tr> + </tr> + </tbody> +</table> + +<p>由<code>reduce</code>返回的值将是最后一次回调返回值(10)。</p> + +<p>你还可以使用{{jsxref("Functions/Arrow_functions", "箭头函数","",1)}}来代替完整的函数。 下面的代码将产生与上面的代码相同的输出:</p> + +<pre class="brush: js notranslate">[0, 1, 2, 3, 4].reduce((prev, curr) => prev + curr );</pre> + +<p>如果你打算提供一个初始值作为<code>reduce()</code>方法的第二个参数,以下是运行过程及结果:</p> + +<pre class="brush: js notranslate">[0, 1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => { + return accumulator + currentValue +}, 10) +</pre> + +<table> + <thead> + <tr> + <th scope="col"><code>callback</code></th> + <th scope="col"><code>accumulator</code></th> + <th scope="col"><code>currentValue</code></th> + <th scope="col"><code>currentIndex</code></th> + <th scope="col"><code>array</code></th> + <th scope="col">return value</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">first call</th> + <td><code>10</code></td> + <td><code>0</code></td> + <td><code>0</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>10</code></td> + </tr> + <tr> + <th scope="row">second call</th> + <td><code>10</code></td> + <td><code>1</code></td> + <td><code>1</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>11</code></td> + </tr> + <tr> + <th scope="row">third call</th> + <td><code>11</code></td> + <td><code>2</code></td> + <td><code>2</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>13</code></td> + </tr> + <tr> + <th scope="row">fourth call</th> + <td><code>13</code></td> + <td><code>3</code></td> + <td><code>3</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>16</code></td> + </tr> + <tr> + <th scope="row">fifth call</th> + <td><code>16</code></td> + <td><code>4</code></td> + <td><code>4</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>20</code></td> + </tr> + </tbody> +</table> + +<p>这种情况下<code>reduce()</code>返回的值是<code>20</code>。</p> + +<h2 id="例子">例子</h2> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +<h3 id="数组里所有值的和">数组里所有值的和</h3> + +<pre class="brush: js notranslate">var sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) { + return accumulator + currentValue; +}, 0); +// 和为 6</pre> + +<p>你也可以写成箭头函数的形式:</p> + +<pre class="brush: js notranslate">var total = [ 0, 1, 2, 3 ].reduce( + ( acc, cur ) => acc + cur, + 0 +);</pre> + +<h3 id="累加对象数组里的值">累加对象数组里的值</h3> + +<p>要累加对象数组中包含的值,必须提供初始值,以便各个item正确通过你的函数。</p> + +<pre class="brush: js notranslate">var initialValue = 0; +var sum = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulator, currentValue) { + return accumulator + currentValue.x; +},initialValue) + +console.log(sum) // logs 6</pre> + +<p>你也可以写成箭头函数的形式:</p> + +<pre class="brush: js notranslate">var initialValue = 0; +var sum = [{x: 1}, {x:2}, {x:3}].reduce( + (accumulator, currentValue) => accumulator + currentValue.x + ,initialValue +); + +console.log(sum) // logs 6 +</pre> + +<h3 id="将二维数组转化为一维">将二维数组转化为一维</h3> + +<pre class="brush: js notranslate">var flattened = [[0, 1], [2, 3], [4, 5]].reduce( + function(a, b) { + return a.concat(b); + }, + [] +); +// flattened is [0, 1, 2, 3, 4, 5] +</pre> + +<p>你也可以写成箭头函数的形式:</p> + +<pre class="brush: js notranslate">var flattened = [[0, 1], [2, 3], [4, 5]].reduce( + ( acc, cur ) => acc.concat(cur), + [] +); + +</pre> + +<h3 id="计算数组中每个元素出现的次数">计算数组中每个元素出现的次数</h3> + +<pre class="brush: js notranslate">var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice']; + +var countedNames = names.reduce(function (allNames, name) { + if (name in allNames) { + allNames[name]++; + } + else { + allNames[name] = 1; + } + return allNames; +}, {}); +// countedNames is: +// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }</pre> + +<h3 id="按属性对object分类">按属性对object分类</h3> + +<pre class="brush: js notranslate">var people = [ + { name: 'Alice', age: 21 }, + { name: 'Max', age: 20 }, + { name: 'Jane', age: 20 } +]; + +function groupBy(objectArray, property) { + return objectArray.reduce(function (acc, obj) { + var key = obj[property]; + if (!acc[key]) { + acc[key] = []; + } + acc[key].push(obj); + return acc; + }, {}); +} + +var groupedPeople = groupBy(people, 'age'); +// groupedPeople is: +// { +// 20: [ +// { name: 'Max', age: 20 }, +// { name: 'Jane', age: 20 } +// ], +// 21: [{ name: 'Alice', age: 21 }] +// } +</pre> + +<h3 id="使用扩展运算符和initialValue绑定包含在对象数组中的数组">使用扩展运算符和initialValue绑定包含在对象数组中的数组</h3> + +<pre class="brush: js notranslate">// friends - 对象数组 +// where object field "books" - list of favorite books +var friends = [{ + name: 'Anna', + books: ['Bible', 'Harry Potter'], + age: 21 +}, { + name: 'Bob', + books: ['War and peace', 'Romeo and Juliet'], + age: 26 +}, { + name: 'Alice', + books: ['The Lord of the Rings', 'The Shining'], + age: 18 +}]; + +// allbooks - list which will contain all friends' books + +// additional list contained in initialValue +var allbooks = friends.reduce(function(prev, curr) { + return [...prev, ...curr.books]; +}, ['Alphabet']); + +// allbooks = [ +// 'Alphabet', 'Bible', 'Harry Potter', 'War and peace', +// 'Romeo and Juliet', 'The Lord of the Rings', +// 'The Shining' +// ] +</pre> + +<h3 id="数组去重">数组去重</h3> + +<div class="blockIndicator note"> +<p>注意: 如果你正在使用一个可以兼容{{jsxref("Set")}} 和 {{jsxref("Array.from()")}} 的环境, 你可以使用<code>let orderedArray = Array.from(new Set(myArray));</code> 来获得一个相同元素被移除的数组。</p> +</div> + +<pre class="brush: js notranslate">let myArray = ['a', 'b', 'a', 'b', 'c', 'e', 'e', 'c', 'd', 'd', 'd', 'd'] +let myOrderedArray = myArray.reduce(function (accumulator, currentValue) { + if (accumulator.indexOf(currentValue) === -1) { + accumulator.push(currentValue) + } + return accumulator +}, []) + +console.log(myOrderedArray)</pre> + +<pre class="brush: js notranslate">let arr = [1,2,1,2,3,5,4,5,3,4,4,4,4]; +let result = arr.sort().reduce((init, current) => { + if(init.length === 0 || init[init.length-1] !== current) { + init.push(current); + } + return init; +}, []); +console.log(result); //[1,2,3,4,5]</pre> + +<h3 id="按顺序运行Promise">按顺序运行Promise</h3> + +<pre class="brush: js notranslate">/** + * Runs promises from array of functions that can return promises + * in chained manner + * + * @param {array} arr - promise arr + * @return {Object} promise object + */ +function runPromiseInSequence(arr, input) { + return arr.reduce( + (promiseChain, currentFunction) => promiseChain.then(currentFunction), + Promise.resolve(input) + ); +} + +// promise function 1 +function p1(a) { + return new Promise((resolve, reject) => { + resolve(a * 5); + }); +} + +// promise function 2 +function p2(a) { + return new Promise((resolve, reject) => { + resolve(a * 2); + }); +} + +// function 3 - will be wrapped in a resolved promise by .then() +function f3(a) { + return a * 3; +} + +// promise function 4 +function p4(a) { + return new Promise((resolve, reject) => { + resolve(a * 4); + }); +} + +const promiseArr = [p1, p2, f3, p4]; +runPromiseInSequence(promiseArr, 10) + .then(console.log); // 1200 +</pre> + +<h3 id="功能型函数管道">功能型函数管道</h3> + +<pre class="brush: js notranslate">// Building-blocks to use for composition +const double = x => x + x; +const triple = x => 3 * x; +const quadruple = x => 4 * x; + +// Function composition enabling pipe functionality +const pipe = (...functions) => input => functions.reduce( + (acc, fn) => fn(acc), + input +); + +// Composed functions for multiplication of specific values +const multiply6 = pipe(double, triple); +const multiply9 = pipe(triple, triple); +const multiply16 = pipe(quadruple, quadruple); +const multiply24 = pipe(double, triple, quadruple); + +// Usage +multiply6(6); // 36 +multiply9(9); // 81 +multiply16(16); // 256 +multiply24(10); // 240 +</pre> + +<h3 id="使用_reduce实现map">使用 reduce实现map</h3> + +<pre class="brush: js notranslate">if (!Array.prototype.mapUsingReduce) { + Array.prototype.mapUsingReduce = function(callback, thisArg) { + return this.reduce(function(mappedArray, currentValue, index, array) { + mappedArray[index] = callback.call(thisArg, currentValue, index, array) + return mappedArray + }, []) + } +} + +[1, 2, , 3].mapUsingReduce( + (currentValue, index, array) => currentValue + index + array.length +) // [5, 7, , 10] +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<pre class="brush: js notranslate">// Production steps of ECMA-262, Edition 5, 15.4.4.21 +// Reference: http://es5.github.io/#x15.4.4.21 +// https://tc39.github.io/ecma262/#sec-array.prototype.reduce +if (!Array.prototype.reduce) { + Object.defineProperty(Array.prototype, 'reduce', { + value: function(callback /*, initialValue*/) { + if (this === null) { + throw new TypeError( 'Array.prototype.reduce ' + + 'called on null or undefined' ); + } + if (typeof callback !== 'function') { + throw new TypeError( callback + + ' is not a function'); + } + + // 1. Let O be ? ToObject(this value). + var o = Object(this); + + // 2. Let len be ? ToLength(? Get(O, "length")). + var len = o.length >>> 0; + + // Steps 3, 4, 5, 6, 7 + var k = 0; + var value; + + if (arguments.length >= 2) { + value = arguments[1]; + } else { + while (k < len && !(k in o)) { + k++; + } + + // 3. If len is 0 and initialValue is not present, + // throw a TypeError exception. + if (k >= len) { + throw new TypeError( 'Reduce of empty array ' + + 'with no initial value' ); + } + value = o[k++]; + } + + // 8. Repeat, while k < len + while (k < len) { + // a. Let Pk be ! ToString(k). + // b. Let kPresent be ? HasProperty(O, Pk). + // c. If kPresent is true, then + // i. Let kValue be ? Get(O, Pk). + // ii. Let accumulator be ? Call( + // callbackfn, undefined, + // « accumulator, kValue, k, O »). + if (k in o) { + value = callback(value, o[k], k, o); + } + + // d. Increase k by 1. + k++; + } + + // 9. Return accumulator. + return value; + } + }); +} +</pre> + +<p>如果您需要兼容不支持<code><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">Object.defineProperty</a></code>的JavaScript引擎,那么最好不要 polyfill <code>Array.prototype</code>方法,因为你无法使其成为<strong>不可枚举</strong>的。</p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.21', 'Array.prototype.reduce')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>初始定语. 实施于 JavaScript 1.8.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.reduce', 'Array.prototype.reduce')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.reduce', 'Array.prototype.reduce')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.reduce")}}</p> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.reduceRight()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/reduceright/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/reduceright/index.html new file mode 100644 index 0000000000..e4846dbfbf --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/reduceright/index.html @@ -0,0 +1,409 @@ +--- +title: Array.prototype.reduceRight() +slug: Web/JavaScript/Reference/Global_Objects/Array/ReduceRight +tags: + - JavaScript + - 原型 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/ReduceRight +--- +<div>{{JSRef}}</div> + +<p><code><strong>reduceRight()</strong></code> 方法接受一个函数作为累加器(accumulator)和数组的每个值(从右到左)将其减少为单个值。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-reduce-right.html")}}</div> + + + +<p>对于从左至右遍历的相似方法请参阅 {{jsxref("Array.prototype.reduce()")}}.</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate"><var>arr.reduceRight(callback(accumulator, currentValue[, index[, array]])[, initialValue])</var></pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>一个回调函数,用于操作数组中的每个元素,它可接受四个参数: + <dl> + <dt><code>accumulator</code></dt> + <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">累加器:</span></span>上一次调用回调函数时,回调函数返回的值。首次调用回调函数时,如果 <code>initialValue</code> 存在,<span class="tlid-translation translation" lang="zh-CN"><span title="">累加器</span></span>即为 <code>initialValue</code>,否则须为数组中的最后一个元素(详见下方 <code>initialValue</code> 处相关说明)。</dd> + <dt><code>currentValue</code></dt> + <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">当前元素:</span></span>当前被处理的元素。</dd> + <dt><code>index</code>{{optional_inline}}</dt> + <dd>数组中当前被处理的元素的索引。</dd> + <dt><code>array</code>{{optional_inline}}</dt> + <dd>调用 <code>reduceRight()</code> 的数组。</dd> + </dl> + </dd> + <dt><code>initialValue</code>{{optional_inline}} </dt> + <dd><span class="tlid-translation translation" lang="zh-CN"><span title="">首次调用</span></span> <code>callback</code> 函数时,<span class="tlid-translation translation" lang="zh-CN"><span title="">累加器 </span></span> <code>accumulator</code> <span class="tlid-translation translation" lang="zh-CN"><span title="">的值</span></span>。如果未提供该初始值,则将使用数组中的最后一个元素,并跳过该元素。如果不给出初始值,则需保证数组不为空。<br> + 否则,在空数组上调用 <code>reduce</code> 或 <code>reduceRight</code> 且未提供初始值(例如 <code>[].reduce( (acc, cur, idx, arr) => {} )</code> )的话,会导致类型错误 <code><a href="/zh-CN/docs/Web/JavaScript/Reference/Errors/Reduce_of_empty_array_with_no_initial_value">TypeError: reduce of empty array with no initial value</a></code>。</dd> + <dt> + <h3 id="返回值">返回值</h3> + </dt> + <dd> + <p>执行之后的返回值。</p> + </dd> +</dl> + +<h2 id="描述">描述</h2> + +<p><code>reduceRight</code> 为数组中每个元素调用一次 <code>callback</code> 回调函数,但是数组中被删除的索引或从未被赋值的索引会跳过。回调函数接受四个参数:初始值(或上次调用回调的返回值)、当前元素值、当前索引,以及调用迭代的当前数组。</p> + +<p>可以像下面这样调用 <code>reduceRight</code> 的回调函数 <code>callback</code>:</p> + +<pre class="brush: js notranslate">array.reduceRight(function(accumulator, currentValue, index, array) { + // ... +});</pre> + +<p>首次调用回调函数时,<code>accumulator</code> 和 <code>currentValue</code> 的可能取值情况有两种:</p> + +<ul> + <li>如果在调用 <code>reduceRight</code> 时提供了 <code>initialValue</code> 参数,则 <code>accumulator</code> 等于 <code>initialValue</code>,<code>currentValue</code> 等于数组中的最后一个元素。</li> + <li>如果没有提供 <code>initialValue</code> 参数,则 <code>accumulator</code> 等于数组最后一个元素, <code>currentValue</code> 等于数组中倒数第二个元素。</li> +</ul> + +<p>如果数组为空,但提供了 <code>initialValue</code> 参数,或如果数组中只有一个元素,且没有提供 <code>initialValue</code> 参数,将会直接返回 <code>initialValue</code> 参数或数组中的那一个元素。这两种情况下,都不会调用 <code>callback</code> 函数。</p> + +<p>如果数组为空,且没有提供 <code>initialValue</code> 参数,则会抛出一个 <code>TypeError</code> 错误。</p> + +<p>最终,首次调用时的情况可汇总为此表:</p> + +<table class="standard-table"> + <thead> + <tr> + <th>数组内元素数量</th> + <th>是否提供 <code>initialValue</code></th> + <th>结果</th> + </tr> + </thead> + <tbody> + <tr> + <td rowspan="2">> 1</td> + <td>未提供</td> + <td><code>accumulator</code> 为<u>数组中</u>(下略)最后一个元素<br> + <code>currentValue</code> 为倒数第二个元素</td> + </tr> + <tr> + <td>提供</td> + <td><code>accumulator</code> 为 <code>initialValue</code><br> + <code>currentValue</code> 为最后一个元素</td> + </tr> + <tr> + <td>= 1</td> + <td>未提供</td> + <td>直接返回数组中的唯一一个元素</td> + </tr> + <tr> + <td rowspan="2">= 0</td> + <td>提供</td> + <td>直接返回 <code>initialValue</code></td> + </tr> + <tr> + <td>未提供</td> + <td>抛出 <code>TypeError</code> 错误</td> + </tr> + </tbody> +</table> + +<p>该函数的完整执行过程见下例:</p> + +<pre class="brush: js notranslate">[0, 1, 2, 3, 4].reduceRight(function(previousValue, currentValue, index, array) { + return previousValue + currentValue; +}); +</pre> + +<p>一共会调用四次回调函数,每次调用的参数及返回值如下:</p> + +<table style="width: 100%;"> + <thead> + <tr> + <th scope="col"><code>callback</code></th> + <th scope="col"><code>previousValue</code></th> + <th scope="col"><code>currentValue</code></th> + <th scope="col"><code>index</code></th> + <th scope="col"><code>array</code></th> + <th scope="col">返回值</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">第一次调用</th> + <td><code>4</code></td> + <td><code>3</code></td> + <td><code>3</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>7</code></td> + </tr> + <tr> + <th scope="row">第二次调用</th> + <td><code>7</code></td> + <td><code>2</code></td> + <td><code>2</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>9</code></td> + </tr> + <tr> + <th scope="row">第三次调用</th> + <td><code>9</code></td> + <td><code>1</code></td> + <td><code>1</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>10</code></td> + </tr> + <tr> + <th scope="row">第四次调用</th> + <td><code>10</code></td> + <td><code>0</code></td> + <td><code>0</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>10</code></td> + </tr> + </tbody> +</table> + +<p><code>reduceRight</code> 返回值是最后一次调用回调的返回值(<code>10</code>)。</p> + +<p>如果提供了一个 <code>initialValue</code> 参数,则结果如下:</p> + +<pre class="brush: js notranslate">[0, 1, 2, 3, 4].reduceRight(function(previousValue, currentValue, index, array) { + return previousValue + currentValue; +}, 10); +</pre> + +<table style="width: 100%;"> + <thead> + <tr> + <th scope="col"><code>callback</code></th> + <th scope="col"><code>previousValue</code></th> + <th scope="col"><code>currentValue</code></th> + <th scope="col"><code>index</code></th> + <th scope="col"><code>array</code></th> + <th scope="col">返回值</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">第一次调用</th> + <td><code>10</code></td> + <td><code>4</code></td> + <td><code>4</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>14</code></td> + </tr> + <tr> + <th scope="row">第二次调用</th> + <td><code>14</code></td> + <td><code>3</code></td> + <td><code>3</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>17</code></td> + </tr> + <tr> + <th scope="row">第三次调用</th> + <td><code>17</code></td> + <td><code>2</code></td> + <td><code>2</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>19</code></td> + </tr> + <tr> + <th scope="row">第四次调用</th> + <td><code>19</code></td> + <td><code>1</code></td> + <td><code>1</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>20</code></td> + </tr> + <tr> + <th scope="row">第五次调用</th> + <td><code>20</code></td> + <td><code>0</code></td> + <td><code>0</code></td> + <td><code>[0,1,2,3,4]</code></td> + <td><code>20</code></td> + </tr> + </tbody> +</table> + +<p>这时,<code>reduceRight</code> 返回值为 20。</p> + +<h2 id="示例">示例</h2> + +<h3 id="求一个数组中所有值的和">求一个数组中所有值的和</h3> + +<pre class="brush: js notranslate">var sum = [0, 1, 2, 3].reduceRight(function(a, b) { + return a + b; +}); +// sum is 6</pre> + +<h3 id="扁平化(flatten)一个二维数组">扁平化(flatten)一个二维数组</h3> + +<pre class="brush: js notranslate">var flattened = [[0, 1], [2, 3], [4, 5]].reduceRight(function(a, b) { + return a.concat(b); +}, []); +// flattened is [4, 5, 2, 3, 0, 1] +</pre> + +<h3 id="运行一个带有回调每个函数将其结果传给下一个的异步函数列表">运行一个带有回调每个函数将其结果传给下一个的异步函数列表</h3> + +<pre class="brush: js notranslate">const waterfall = (...functions) => (callback, ...args) => + functions.reduceRight( + (composition, fn) => (...results) => fn(composition, ...results), + callback + )(...args); + +const randInt = max => Math.floor(Math.random() * max) + +const add5 = (callback, x) => { + setTimeout(callback, randInt(1000), x + 5); +}; +const mult3 = (callback, x) => { + setTimeout(callback, randInt(1000), x * 3); +}; +const sub2 = (callback, x) => { + setTimeout(callback, randInt(1000), x - 2); +}; +const split = (callback, x) => { + setTimeout(callback, randInt(1000), x, x); +}; +const add = (callback, x, y) => { + setTimeout(callback, randInt(1000), x + y); +}; +const div4 = (callback, x) => { + setTimeout(callback, randInt(1000), x / 4); +}; + +const computation = waterfall(add5, mult3, sub2, split, add, div4); +computation(console.log, 5) // -> 14 + +// same as: + +const computation2 = (input, callback) => { + const f6 = x=> div4(callback, x); + const f5 = (x, y) => add(f6, x, y); + const f4 = x => split(f5, x); + const f3 = x => sub2(f4, x); + const f2 = x => mult3(f3, x); + add5(f2, input); +}</pre> + +<h3 id="展示_reduce_与_reduceRight_之间的区别">展示 <code>reduce</code> 与 <code>reduceRight</code> 之间的区别</h3> + +<pre class="brush: js notranslate">var a = ['1', '2', '3', '4', '5']; +var left = a.reduce(function(prev, cur) { return prev + cur; }); +var right = a.reduceRight(function(prev, cur) { return prev + cur; }); + +console.log(left); // "12345" +console.log(right); // "54321"</pre> + +<h3 id="定义可组合函数">定义可组合函数</h3> + +<p>组合函数的概念简单,它只是简单地结合了多个函数。它是一个从右向左流动的函数,用上一个函数的输出调用每个函数。</p> + +<pre class="brush: js notranslate">/** + * Function Composition is way in which result of one function can + * be passed to another and so on. + * + * h(x) = f(g(x)) + * + * Function execution happens right to left + * + * https://en.wikipedia.org/wiki/Function_composition + */ + +const compose = (...args) => (value) => args.reduceRight((acc, fn) => fn(acc), value) + +// Increament passed number +const inc = (n) => n + 1 + +// Doubles the passed value +const double = (n) => n * 2 + +// using composition function +console.log(compose(double, inc)(2)); // 6 + +// using composition function +console.log(compose(inc, double)(2)); // 5</pre> + +<h2 id="兼容旧环境(Polyfill)">兼容旧环境(Polyfill)</h2> + +<p><code>reduceRight</code> 被添加到 ECMA-262 标准第 5 版,因此它在某些实现环境中可能不被支持。把下面的代码添加到脚本开头可以解决此问题,从而允许在那些没有原生支持 <code>reduceRight</code> 的实现环境中使用它。</p> + +<pre class="brush: js notranslate">// Production steps of ECMA-262, Edition 5, 15.4.4.22 +// Reference: http://es5.github.io/#x15.4.4.22 +if ('function' !== typeof Array.prototype.reduceRight) { + Array.prototype.reduceRight = function(callback /*, initialValue*/) { + 'use strict'; + if (null === this || 'undefined' === typeof this) { + throw new TypeError('Array.prototype.reduceRight called on null or undefined'); + } + if ('function' !== typeof callback) { + throw new TypeError(callback + ' is not a function'); + } + var t = Object(this), len = t.length >>> 0, k = len - 1, value; + if (arguments.length >= 2) { + value = arguments[1]; + } else { + while (k >= 0 && !(k in t)) { + k--; + } + if (k < 0) { + throw new TypeError('reduceRight of empty array with no initial value'); + } + value = t[k--]; + } + for (; k >= 0; k--) { + if (k in t) { + value = callback(value, t[k], k, t); + } + } + return value; + }; +} +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.22', 'Array.prototype.reduceRight')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition.<br> + Implemented in JavaScript 1.8</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.reduceright', 'Array.prototype.reduceRight')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.reduceright', 'Array.prototype.reduceRight')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.reduceRight")}}</p> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.reduce()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/reverse/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/reverse/index.html new file mode 100644 index 0000000000..a9c984245f --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/reverse/index.html @@ -0,0 +1,141 @@ +--- +title: Array.prototype.reverse() +slug: Web/JavaScript/Reference/Global_Objects/Array/reverse +tags: + - Array + - Array.prototype.reverse() + - JavaScript + - 原型 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/reverse +--- +<div>{{JSRef}}</div> + +<p><code><strong>reverse()</strong></code> 方法将数组中元素的位置颠倒,并返回该数组。数组的第一个元素会变成最后一个,数组的最后一个元素变成第一个。该方法会改变原数组。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-reverse.html")}}</div> + +<div></div> + +<div></div> + +<h2 id="语法" style="margin-bottom: 20px; line-height: 30px;">语法</h2> + +<pre class="syntaxbox"><code><var> arr</var>.reverse()</code></pre> + +<h3 id="返回值" style="line-height: 24px;">返回值</h3> + +<p>颠倒后的数组。</p> + +<h2 id="描述" style="margin-bottom: 20px; line-height: 30px;">描述</h2> + +<p><code>reverse</code> 方法颠倒数组中元素的位置,改变了数组,并返回该数组的引用。</p> + +<p>reverse方法是特意类化的;此方法可被 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call" title="The call() method calls a function with a given this value and arguments provided individually.">called</a> 或 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply" title="The apply() method calls a function with a given this value, and arguments provided as an array (or an array-like object).">applied</a>于类似数组对象。对象如果不包含反映一系列连续的、基于零的数值属性中的最后一个长度的属性,则该对象可能不会以任何有意义的方式运行。</p> + +<h2 id="示例" style="margin-bottom: 20px; line-height: 30px;">示例</h2> + +<h3 id="颠倒数组中的元素" style="line-height: 24px;">颠倒数组中的元素</h3> + +<p>下例将会创建一个数组 sourceArray,其包含三个元素,然后颠倒该数组。</p> + +<p> <code>reverse()</code> 的调用返回了一个颠倒后的数组 <code>a</code>的引用。</p> + +<pre><code>const a = [1, 2, 3]; + +console.log(a); // [1, 2, 3] + +a.reverse(); + +console.log(a); // [3, 2, 1]</code></pre> + +<h3 id="颠倒类数组中的元素">颠倒类数组中的元素</h3> + +<p>下例创造了一个类数组对象 <code>a</code>, 包含3个元素和一个 length 属性, 然后颠倒这个类数组对象。 <code>reverse()</code> 的调用返回一个颠倒后的类数组对象 <code>a</code>的引用。</p> + +<pre><code>const a = {0: 1, 1: 2, 2: 3, length: 3}; + +console.log(a); // {0: 1, 1: 2, 2: 3, length: 3} + +Array.prototype.reverse.call(a); //same syntax for using apply() + +console.log(a); // {0: 3, 1: 2, 2: 1, length: 3}</code></pre> + +<h2 id="Specifications">Specifications</h2> + +<table> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.1.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.8', 'Array.prototype.reverse')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.reverse', 'Array.prototype.reverse')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.reverse', 'Array.prototype.reverse')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> <br> + </td> + </tr> + </tbody> +</table> + +<h2 id="规范" style="margin-bottom: 20px; line-height: 30px;">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.1</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.8', 'Array.prototype.reverse')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.reverse', 'Array.prototype.reverse')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性" style="margin-bottom: 20px; line-height: 30px;">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.reverse")}}</p> +</div> +</div> + +<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px;">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.join()")}}</li> + <li>{{jsxref("Array.prototype.sort()")}}</li> + <li>{{jsxref("TypedArray.prototype.reverse()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/shift/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/shift/index.html new file mode 100644 index 0000000000..3675c12bc4 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/shift/index.html @@ -0,0 +1,129 @@ +--- +title: Array.prototype.shift() +slug: Web/JavaScript/Reference/Global_Objects/Array/shift +tags: + - Array.prototype.shift() + - JavaScript + - 原型 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/shift +--- +<div>{{JSRef}}</div> + +<p><code><strong>shift()</strong></code> 方法从数组中删除<strong>第一个</strong>元素,并返回该元素的值。此方法更改数组的长度。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-shift.html")}}</div> + +<p class="hidden">这份交互测试源码存储在Github仓库中。如果你想为这份交互测试源码做贡献, 请克隆 <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> 同时提交一个pull request.</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox"><code><var>arr</var>.shift()</code></pre> + + + +<h3 id="返回值">返回值 </h3> + +<p>从数组中删除的元素; 如果数组为空则返回{{jsxref("undefined")}} 。 </p> + +<h2 id="描述">描述</h2> + +<p><code>shift</code> 方法移除索引为 0 的元素(即第一个元素),并返回被移除的元素,其他元素的索引值随之减 1。如果 {{jsxref("Array.length", "length")}} 属性的值为 0 (长度为 0),则返回 {{jsxref("undefined")}}。</p> + +<p><code>shift</code> 方法并不局限于数组:这个方法能够通过 {{jsxref("Function.call", "call")}} 或 {{jsxref("Function.apply", "apply")}} 方法作用于类似数组的对象上。但是对于没有 length 属性(从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。</p> + +<p>{{jsxref("Array.prototype.pop()")}} 有着和 <code>shift</code>相似的行为, 但是是作用在数组的最后一个元素上的。</p> + +<h2 id="示例">示例</h2> + +<h3 id="移除数组中的一个元素">移除数组中的一个元素</h3> + +<p>以下代码显示了删除其第一个元素之前和之后的myFish数组。它还显示已删除的元素:</p> + +<pre class="brush: js">let myFish = ['angel', 'clown', 'mandarin', 'surgeon']; + +console.log('调用 shift 之前: ' + myFish); +// "调用 shift 之前: angel,clown,mandarin,surgeon" + +var shifted = myFish.shift(); + +console.log('调用 shift 之后: ' + myFish); +// "调用 shift 之后: clown,mandarin,surgeon" + +console.log('被删除的元素: ' + shifted); +// "被删除的元素: angel"</pre> + +<pre><code>var myFish = ['angel', 'clown', 'mandarin', 'surgeon']; + +console.log('myFish before:', JSON.stringify(myFish)); +// myFish before: ['angel', 'clown', 'mandarin', 'surgeon'] + +var shifted = myFish.shift(); + +console.log('myFish after:', myFish); +// myFish after: ['clown', 'mandarin', 'surgeon'] + +console.log('Removed this element:', shifted); +// Removed this element: angel</code></pre> + +<h3 id="在while循环中使用shift">在while循环中使用shift()</h3> + +<p>shift() 方法经常用于while loop的环境中.。下例中每个循环将要从一个数组中移除下一项元素,直至它成为空数组。</p> + +<pre><code>var names = ["Andrew", "Edward", "Paul", "Chris" ,"John"]; + +while( (i = names.shift()) !== undefined ) { + console.log(i); +} +// Andrew, Edward, Paul, Chris, John</code></pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Initial definition. Implemented in JavaScript 1.2.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.9', 'Array.prototype.shift')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.shift', 'Array.prototype.shift')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.shift', 'Array.prototype.shift')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器支持">浏览器支持</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.shift")}}</p> +</div> +</div> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.push()")}}</li> + <li>{{jsxref("Array.prototype.pop()")}}</li> + <li>{{jsxref("Array.prototype.unshift()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/slice/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/slice/index.html new file mode 100644 index 0000000000..eb68df4907 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/slice/index.html @@ -0,0 +1,253 @@ +--- +title: Array.prototype.slice() +slug: Web/JavaScript/Reference/Global_Objects/Array/slice +tags: + - Array + - JavaScript + - Prototype + - 原型 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/slice +--- +<div>{{JSRef}}</div> + +<p><code><strong title="切片">slice()</strong></code> 方法返回一个新的数组对象,这一对象是一个由 <code>begin</code> 和 <code>end</code> 决定的原数组的<strong>浅拷贝</strong>(包括 <code>begin</code>,不包括<code>end</code>)。原始数组不会被改变。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-slice.html")}}</div> + +<p class="hidden">The source for this interactive demo is stored in a GitHub repository. If you'd like to contribute to the interactive demo project, please clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> and send us a pull request.</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate"><var>arr</var>.slice([<var>begin</var>[, <var>end</var>]])</pre> + +<h2 id="参数">参数</h2> + +<dl> + <dt><code>begin</code> {{optional_inline}}</dt> + <dd>提取起始处的索引(从 <code>0</code> 开始),从该索引开始提取原数组元素。</dd> + <dd>如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取,<code>slice(-2)</code> 表示提取原数组中的倒数第二个元素到最后一个元素(包含最后一个元素)。</dd> + <dd>如果省略 <code>begin</code>,则 <code>slice</code> 从索引 <code>0</code> 开始。</dd> + <dd>如果 <code>begin</code> 超出原数组的索引范围,则会返回空数组。</dd> +</dl> + +<dl> + <dt><code>end</code> {{optional_inline}}</dt> + <dd>提取终止处的索引(从 <code>0</code> 开始),在该索引处结束提取原数组元素。<code>slice</code> 会提取原数组中索引从 <code>begin</code> 到 <code>end</code> 的所有元素(包含 <code>begin</code>,但不包含 <code>end</code>)。</dd> + <dd><code>slice(1,4)</code> 会提取原数组中从第二个元素开始一直到第四个元素的所有元素 (索引为 1, 2, 3的元素)。</dd> + <dd>如果该参数为负数, 则它表示在原数组中的倒数第几个元素结束抽取。 <code>slice(-2,-1)</code> 表示抽取了原数组中的倒数第二个元素到最后一个元素(不包含最后一个元素,也就是只有倒数第二个元素)。</dd> + <dd>如果 <code>end</code> 被省略,则 <code>slice</code> 会一直提取到原数组末尾。</dd> + <dd>如果 <code>end</code> 大于数组的长度,<code>slice</code> 也会一直提取到原数组末尾。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>一个含有被提取元素的新数组。</p> + +<h2 id="描述">描述</h2> + +<p><code>slice</code> 不会修改原数组,只会返回一个浅复制了原数组中的元素的一个新数组。原数组的元素会按照下述规则拷贝:</p> + +<ul> + <li>如果该元素是个对象引用 (不是实际的对象),<code>slice</code> 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。如果被引用的对象发生改变,则新的和原来的数组中的这个元素也会发生改变。</li> +</ul> + +<ul> + <li>对于字符串、数字及布尔值来说(不是 {{jsxref("Global_Objects/String", "String")}}、{{jsxref("Global_Objects/Number", "Number")}} 或者 {{jsxref("Boolean")}} 对象),<code>slice</code> 会拷贝这些值到新的数组里。在别的数组里修改这些字符串或数字或是布尔值,将不会影响另一个数组。</li> +</ul> + +<p>如果向两个数组任一中添加了新元素,则另一个不会受到影响。</p> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="返回现有数组的一部分">返回现有数组的一部分</h3> + +<pre class="brush: js notranslate">var fruits = ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango']; +var citrus = fruits.slice(1, 3); + +// fruits contains ['Banana', 'Orange', 'Lemon', 'Apple', 'Mango'] +// citrus contains ['Orange','Lemon'] +</pre> + +<div class="standardNoteBlock"> +<p class="syntaxbox"><strong>译者注:citrus</strong> <em>[n.]</em> 柑橘类果实</p> +</div> + +<h3 id="使用_slice">使用 <code>slice</code></h3> + +<p>在下例中, <code>slice</code> 从 <code>myCar</code> 中创建了一个新数组<code>newCar</code>。两个数组都包含了一个 <code>myHonda</code> 对象的引用。当 <code>myHonda</code> 的 <code>color</code> 属性改变为 <code>purple</code>,则两个数组中的对应元素都会随之改变。</p> + +<pre class="brush: js notranslate">// 使用 slice 方法从 myCar 中创建一个 newCar。 +var myHonda = { color: 'red', wheels: 4, engine: { cylinders: 4, size: 2.2 } }; +var myCar = [myHonda, 2, "cherry condition", "purchased 1997"]; +var newCar = myCar.slice(0, 2); + +// 输出 myCar、newCar 以及各自的 myHonda 对象引用的 color 属性。 +console.log(' myCar = ' + JSON.stringify(myCar)); +console.log('newCar = ' + JSON.stringify(newCar)); +console.log(' myCar[0].color = ' + JSON.stringify(myCar[0].color)); +console.log('newCar[0].color = ' + JSON.stringify(newCar[0].color)); + +// 改变 myHonda 对象的 color 属性. +myHonda.color = 'purple'; +console.log('The new color of my Honda is ' + myHonda.color); + +//输出 myCar、newCar 中各自的 myHonda 对象引用的 color 属性。 +console.log(' myCar[0].color = ' + myCar[0].color); +console.log('newCar[0].color = ' + newCar[0].color); +</pre> + +<p>上述代码输出:</p> + +<pre class="brush: js notranslate"> myCar = [{color: 'red', wheels: 4, engine: {cylinders: 4, size: 2.2}}, 2, + 'cherry condition', 'purchased 1997'] +newCar = [{color: 'red', wheels: 4, engine: {cylinders: 4, size: 2.2}}, 2] + myCar[0].color = red +newCar[0].color = red +The new color of my Honda is purple + myCar[0].color = purple +newCar[0].color = purple +</pre> + +<h2 id="Array-like" name="Array-like">类数组(Array-like)对象</h2> + +<p><code>slice</code> 方法可以用来将一个类数组(Array-like)对象/集合转换成一个新数组。你只需将该方法绑定到这个对象上。 一个函数中的 {{jsxref("Functions/arguments", "arguments")}} 就是一个类数组对象的例子。</p> + +<pre class="brush: js notranslate">function list() { + return Array.prototype.slice.call(arguments); +} + +var list1 = list(1, 2, 3); // [1, 2, 3] +</pre> + +<p>除了使用 <code>Array.prototype.slice.call(</code><code>arguments</code><code>)</code>,你也可以简单的使用 <code>[].slice.call(arguments)</code> 来代替。另外,你可以使用 <code>bind</code> 来简化该过程。</p> + +<pre class="brush: js notranslate">var unboundSlice = Array.prototype.slice; +var slice = Function.prototype.call.bind(unboundSlice); + +function list() { + return slice(arguments); +} + +var list1 = list(1, 2, 3); // [1, 2, 3] +</pre> + +<h2 id="精简跨浏览器行为">精简跨浏览器行为</h2> + +<p>根据规范,使用 <code>Array.prototype.slice</code> 转换宿主对象(如 DOM 对象)时,不必遵循 Mozilla 的默认行为,即可以转化任何符合条件的伪数组宿主对象为数组,IE < 9 没有遵循,而 IE9 + 遵循这个行为,但是稍加改造可以使其在跨浏览器使用时更可靠。只要其他现代浏览器继续支持该行为,目前 IE 9+、FireFox、Chrome、Safari 以及 Opera 都支持,开发者在使用下面代码时遍历 DOM 时就不会被该方法的字面意义误导,即 IE < 9 不能转化 DOM Collections。开发者可以安全地根据语义知道该方法的实际上的标准行为。(下面的代码还修正了 IE 中 <code>slice()</code> 方法第二个参数不允许为显式的 {{jsxref("Global_Objects/null", "null")}}/{{jsxref("Global_Objects/undefined", "undefined")}} 值的问题,其他现代浏览器,包括 IE9+ 都允许)。</p> + +<pre class="brush: js notranslate">/** + * Shim for "fixing" IE's lack of support (IE < 9) for applying slice + * on host objects like NamedNodeMap, NodeList, and HTMLCollection + * (technically, since host objects have been implementation-dependent, + * at least before ES2015, IE hasn't needed to work this way). + * Also works on strings, fixes IE < 9 to allow an explicit undefined + * for the 2nd argument (as in Firefox), and prevents errors when + * called on other DOM objects. + */ +(function () { + 'use strict'; + var _slice = Array.prototype.slice; + + try { + // Can't be used with DOM elements in IE < 9 + _slice.call(document.documentElement); + } catch (e) { // Fails in IE < 9 + // This will work for genuine arrays, array-like objects, + // NamedNodeMap (attributes, entities, notations), + // NodeList (e.g., getElementsByTagName), HTMLCollection (e.g., childNodes), + // and will not fail on other DOM objects (as do DOM elements in IE < 9) + Array.prototype.slice = function(begin, end) { + // IE < 9 gets unhappy with an undefined end argument + end = (typeof end !== 'undefined') ? end : this.length; + + // For native Array objects, we use the native slice function + if (Object.prototype.toString.call(this) === '[object Array]'){ + return _slice.call(this, begin, end); + } + + // For array like object we handle it ourselves. + var i, cloned = [], + size, len = this.length; + + // Handle negative value for "begin" + var start = begin || 0; + start = (start >= 0) ? start : Math.max(0, len + start); + + // Handle negative value for "end" + var upTo = (typeof end == 'number') ? Math.min(end, len) : len; + if (end < 0) { + upTo = len + end; + } + + // Actual expected size of the slice + size = upTo - start; + + if (size > 0) { + cloned = new Array(size); + if (this.charAt) { + for (i = 0; i < size; i++) { + cloned[i] = this.charAt(start + i); + } + } else { + for (i = 0; i < size; i++) { + cloned[i] = this[start + i]; + } + } + } + + return cloned; + }; + } +}()); +</pre> + +<h2 id="规范" style="margin-bottom: 20px; line-height: 30px;">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Initial definition.<br> + Implemented in JavaScript 1.2</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.10', 'Array.prototype.slice')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.slice', 'Array.prototype.slice')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.slice', 'Array.prototype.slice')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性" style="margin-bottom: 20px; line-height: 30px;">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.slice")}}</p> +</div> + +<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px;">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.splice()")}}</li> + <li>{{jsxref("Function.prototype.call()")}}</li> + <li>{{jsxref("Function.prototype.bind()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/some/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/some/index.html new file mode 100644 index 0000000000..734cace600 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/some/index.html @@ -0,0 +1,215 @@ +--- +title: Array.prototype.some() +slug: Web/JavaScript/Reference/Global_Objects/Array/some +tags: + - Array + - ECMAScript5 + - JavaScript + - Method + - Prototype + - Reference +translation_of: Web/JavaScript/Reference/Global_Objects/Array/some +--- +<div>{{JSRef}}</div> + +<p><code><strong>some()</strong></code> 方法测试数组中是不是至少有1个元素通过了被提供的函数测试。它返回的是一个Boolean类型的值。</p> + +<div class="note"> +<p><strong>注意:</strong>如果用一个空数组进行测试,在任何情况下它返回的都是<code>false</code>。</p> +</div> + +<div>{{EmbedInteractiveExample("pages/js/array-some.html")}}</div> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox"><code><em>arr</em>.some(<em>callback(element[, index[, array]])[, thisArg]</em>)</code></pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>用来测试每个元素的函数,接受三个参数: + <dl> + <dt><code>element</code></dt> + <dd>数组中正在处理的元素。</dd> + <dt><code>index</code> {{Optional_inline}}</dt> + <dd>数组中正在处理的元素的索引值。</dd> + <dt><code>array</code>{{Optional_inline}}</dt> + <dd><code>some()</code>被调用的数组。</dd> + </dl> + </dd> + <dt><code>thisArg</code>{{Optional_inline}}</dt> + <dd>执行 <code>callback</code> 时使用的 <code>this</code> 值。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>数组中有至少一个元素通过回调函数的测试就会返回<strong><code>true</code></strong>;所有元素都没有通过回调函数的测试返回值才会为false。</p> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>some()</code> 为数组中的每一个元素执行一次 <code>callback</code> 函数,直到找到一个使得 callback 返回一个“真值”(即可转换为布尔值 true 的值)。如果找到了这样一个值,<code>some()</code> 将会立即返回 <code>true</code>。否则,<code>some()</code> 返回 <code>false</code>。<code>callback</code> 只会在那些”有值“的索引上被调用,不会在那些被删除或从来未被赋值的索引上调用。</p> + +<p><code style="font-style: normal; line-height: 1.5;">callback</code><span style="line-height: 1.5;"> 被调用时传入三个参数:元素的值,元素的索引,被遍历的数组。</span></p> + +<p>如果一个<code>thisArg</code>参数提供给some(),它将被用作调用的 <code>callback</code>的 <code>this</code> 值。否则, 它的 <code>this</code> value将是 <code>undefined</code>。<code>this</code>的值最终通过callback来观察,根据 <a href="/en-US/docs/Web/JavaScript/Reference/Operators/this">the usual rules for determining the <code>this</code> seen by a function</a>的this判定规则来确定。</p> + +<p><code>some()</code> 被调用时不会改变数组。</p> + +<p><code>some()</code> 遍历的元素的范围在第一次调用 <code>callback</code>. 前就已经确定了。在调用 <code>some()</code> 后被添加到数组中的值不会被 <code>callback</code> 访问到。如果数组中存在且还未被访问到的元素被 <code>callback</code> 改变了,则其传递给 <code>callback</code> 的值是 <code>some()</code> 访问到它那一刻的值。已经被删除的元素不会被访问到。</p> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="Example_Testing_size_of_all_array_elements" name="Example:_Testing_size_of_all_array_elements">测试数组元素的值</h3> + +<p>下面的例子检测在数组中是否有元素大于 10。</p> + +<pre class="brush: js">function isBiggerThan10(element, index, array) { + return element > 10; +} + +[2, 5, 8, 1, 4].some(isBiggerThan10); // false +[12, 5, 8, 1, 4].some(isBiggerThan10); // true</pre> + +<h3 id="使用箭头函数测试数组元素的值">使用箭头函数测试数组元素的值</h3> + +<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">箭头函数</a> 可以通过更简洁的语法实现相同的用例.</p> + +<pre class="brush: js"><code>[2, 5, 8, 1, 4].some(x => x > 10); // false +[12, 5, 8, 1, 4].some(x => x > 10); // true</code></pre> + +<p>{{ EmbedLiveSample('Testing_array_elements_using_arrow_functions', '', '', '', 'Web/JavaScript/Reference/Global_Objects/Array/some') }}</p> + +<h3 id="判断数组元素中是否存在某个值">判断数组元素中是否存在某个值</h3> + +<p>此例中为模仿 <code>includes()</code> 方法, 若元素在数组中存在, 则回调函数返回值为 <code>true</code> :</p> + +<pre class="brush: js">var fruits = ['apple', 'banana', 'mango', 'guava']; + +function checkAvailability(arr, val) { + return arr.some(function(arrVal) { + return val === arrVal; + }); +} + +checkAvailability(fruits, 'kela'); // false +checkAvailability(fruits, 'banana'); // true</pre> + +<p>{{ EmbedLiveSample('Checking_whether_a_value_exists_in_an_array', '', '', '', 'Web/JavaScript/Reference/Global_Objects/Array/some') }}</p> + +<h3 id="使用箭头函数判断数组元素中是否存在某个值">使用箭头函数判断数组元素中是否存在某个值</h3> + +<pre class="brush: js">var fruits = ['apple', 'banana', 'mango', 'guava']; + +function checkAvailability(arr, val) { + return arr.some(arrVal => val === arrVal); +} + +checkAvailability(fruits, 'kela'); // false +checkAvailability(fruits, 'banana'); // true</pre> + +<p>{{ EmbedLiveSample('Checking_whether_a_value_exists_using_an_arrow_function', '', '', '', 'Experiment:StaticExamplesOnTop/JavaScript/Array/some') }}</p> + + + +<h3 id="将任意值转换为布尔类型">将任意值转换为布尔类型</h3> + +<pre class="brush: js">var TRUTHY_VALUES = [true, 'true', 1]; + +function getBoolean(value) { + 'use strict'; + + if (typeof value === 'string') { + value = value.toLowerCase().trim(); + } + + return TRUTHY_VALUES.some(function(t) { + return t === value; + }); +} + +getBoolean(false); // false +getBoolean('false'); // false +getBoolean(1); // true +getBoolean('true'); // true +</pre> + +<p>{{ EmbedLiveSample('Converting_any_value_to_Boolean', '', '', '', 'Web/JavaScript/Reference/Global_Objects/Array/some') }}</p> + +<h2 id="Compatibility" name="Compatibility">Polyfill</h2> + +<p>在第 5 版时,<code>some()</code> 被添加进 ECMA-262 标准;这样导致某些实现环境可能不支持它。你可以把下面的代码插入到脚本的开头来解决此问题,从而允许在那些没有原生支持它的实现环境中使用它。该算法是 ECMA-262 第 5 版中指定的算法,假定 <code>Object </code>和 <code>TypeError</code> 拥有他们的初始值,且 <code>fun.call</code> 等价于 <code>{{jsxref("Function.prototype.call")}}</code>。</p> + +<pre class="brush: js">// Production steps of ECMA-262, Edition 5, 15.4.4.17 +// Reference: http://es5.github.io/#x15.4.4.17 +if (!Array.prototype.some) { + Array.prototype.some = function(fun/*, thisArg*/) { + 'use strict'; + + if (this == null) { + throw new TypeError('Array.prototype.some called on null or undefined'); + } + + if (typeof fun !== 'function') { + throw new TypeError(); + } + + var t = Object(this); + var len = t.length >>> 0; + + var thisArg = arguments.length >= 2 ? arguments[1] : void 0; + for (var i = 0; i < len; i++) { + if (i in t && fun.call(thisArg, t[i], i, t)) { + return true; + } + } + + return false; + }; +}</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.17', 'Array.prototype.some')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> + <p>Initial definition. Implemented in JavaScript 1.6.</p> + </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.some', 'Array.prototype.some')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.some', 'Array.prototype.some')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容">浏览器兼容</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.some")}}</p> +</div> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.find()")}}</li> + <li>{{jsxref("Array.prototype.forEach()")}}</li> + <li>{{jsxref("Array.prototype.every()")}}</li> + <li>{{jsxref("TypedArray.prototype.some()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/sort/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/sort/index.html new file mode 100644 index 0000000000..e9f9808420 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/sort/index.html @@ -0,0 +1,265 @@ +--- +title: Array.prototype.sort() +slug: Web/JavaScript/Reference/Global_Objects/Array/sort +tags: + - Array + - Array & sort + - JavaScript + - Prototype + - sort +translation_of: Web/JavaScript/Reference/Global_Objects/Array/sort +--- +<div>{{JSRef}}</div> + +<p><code><strong>sort()</strong></code> 方法用<a href="https://en.wikipedia.org/wiki/In-place_algorithm">原地算法</a>对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的</p> + +<p>由于它取决于具体实现,因此无法保证排序的时间和空间复杂性。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-sort.html")}}</div> + + + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox"><var>arr</var>.sort(<var>[compareFunction]</var>) +</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>compareFunction</code> {{optional_inline}}</dt> + <dd>用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。 + <dl> + <dt><code>firstEl</code></dt> + <dd>第一个用于比较的元素。</dd> + <dt><code>secondEl</code></dt> + <dd>第二个用于比较的元素。</dd> + </dl> + </dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>排序后的数组。请注意,数组已原地排序,并且不进行复制。</p> + +<h2 id="Description" name="Description">描述</h2> + +<p>如果没有指明 <code>compareFunction</code> ,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。例如 "Banana" 会被排列到 "cherry" 之前。当数字按由小到大排序时,9 出现在 80 之前,但因为(没有指明 <code>compareFunction</code>),比较的数字会先被转换为字符串,所以在Unicode顺序上 "80" 要比 "9" 要靠前。</p> + +<p>如果指明了 <code>compareFunction</code> ,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:</p> + +<ul> + <li>如果 <code>compareFunction(a, b)</code> 小于 0 ,那么 a 会被排列到 b 之前;</li> +</ul> + +<ul> + <li>如果 <code>compareFunction(a, b)</code> 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);</li> +</ul> + +<ul> + <li>如果 <code>compareFunction(a, b)</code> 大于 0 , b 会被排列到 a 之前。</li> + <li><code>compareFunction(a, b)</code> 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。</li> +</ul> + +<p>所以,比较函数格式如下:</p> + +<pre class="brush: js">function compare(a, b) { + if (a < b ) { // 按某种排序标准进行比较, a 小于 b + return -1; + } + if (a > b ) { + return 1; + } + // a must be equal to b + return 0; +} +</pre> + +<p>要比较数字而非字符串,比较函数可以简单的以 a 减 b,如下的函数将会将数组升序排列</p> + +<pre class="brush: js">function compareNumbers(a, b) { + return a - b; +} +</pre> + +<p><code>sort</code> 方法可以使用 {{jsxref("Operators/function", "函数表达式", "", 1)}} 方便地书写:</p> + +<pre class="brush: js">var numbers = [4, 2, 5, 1, 3]; +numbers.sort(function(a, b) { + return a - b; +}); +console.log(numbers); + +也可以写成: +var numbers = [4, 2, 5, 1, 3]; +numbers.sort((a, b) => a - b); +console.log(numbers); + +// [1, 2, 3, 4, 5] +</pre> + +<p>对象可以按照某个属性排序:</p> + +<pre class="brush: js line-numbers language-js">var items = [ + { name: 'Edward', value: 21 }, + { name: 'Sharpe', value: 37 }, + { name: 'And', value: 45 }, + { name: 'The', value: -12 }, + { name: 'Magnetic' }, + { name: 'Zeros', value: 37 } +]; + +// sort by value +items.sort(function (a, b) { + return (a.value - b.value) +}); + +<code class="language-js"><span class="comment token">// sort by name</span> +items<span class="punctuation token">.</span><span class="function token">sort</span><span class="punctuation token">(</span><span class="keyword token">function</span><span class="punctuation token">(</span>a<span class="punctuation token">,</span> b<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">var</span> nameA <span class="operator token">=</span> a<span class="punctuation token">.</span>name<span class="punctuation token">.</span><span class="function token">toUpperCase</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// ignore upper and lowercase</span> + <span class="keyword token">var</span> nameB <span class="operator token">=</span> b<span class="punctuation token">.</span>name<span class="punctuation token">.</span><span class="function token">toUpperCase</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> <span class="comment token">// ignore upper and lowercase</span> + <span class="keyword token">if</span> <span class="punctuation token">(</span>nameA <span class="operator token"><</span> nameB<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">return</span> <span class="operator token">-</span><span class="number token">1</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> + <span class="keyword token">if</span> <span class="punctuation token">(</span>nameA <span class="operator token">></span> nameB<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">return</span> <span class="number token">1</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span></code> + + <span class="comment token">// names must be equal</span> + <span class="keyword token">return</span> <span class="number token">0</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></pre> + +<h2 id="Examples" name="Examples">示例</h2> + +<h3 id="Example_Creating.2C_displaying.2C_and_sorting_an_array" name="Example:_Creating.2C_displaying.2C_and_sorting_an_array">创建、显示及排序数组</h3> + +<p>下述示例创建了四个数组,并展示原数组。之后对数组进行排序。对比了数字数组分别指定与不指定比较函数的结果。</p> + +<pre class="brush: js">var stringArray = ["Blue", "Humpback", "Beluga"]; +var numericStringArray = ["80", "9", "700"]; +var numberArray = [40, 1, 5, 200]; +var mixedNumericArray = ["80", "9", "700", 40, 1, 5, 200]; + +function compareNumbers(a, b) +{ + return a - b; +} + +console.log('stringArray:' + stringArray.join()); +console.log('Sorted:' + stringArray.sort()); + +console.log('numberArray:' + numberArray.join()); +console.log('Sorted without a compare function:'+ numberArray.sort()); +console.log('Sorted with compareNumbers:'+ numberArray.sort(compareNumbers)); + +console.log('numericStringArray:'+ numericStringArray.join()); +console.log('Sorted without a compare function:'+ numericStringArray.sort()); +console.log('Sorted with compareNumbers:'+ numericStringArray.sort(compareNumbers)); + +console.log('mixedNumericArray:'+ mixedNumericArray.join()); +console.log('Sorted without a compare function:'+ mixedNumericArray.sort()); +console.log('Sorted with compareNumbers:'+ mixedNumericArray.sort(compareNumbers)); +</pre> + +<p>该示例的返回结果如下。输出显示,当使用比较函数后,数字数组会按照数字大小排序。</p> + +<pre class="brush: js">stringArray: Blue,Humpback,Beluga +Sorted: Beluga,Blue,Humpback + +numberArray: 40,1,5,200 +Sorted without a compare function: 1,200,40,5 +Sorted with compareNumbers: 1,5,40,200 + +numericStringArray: 80,9,700 +Sorted without a compare function: 700,80,9 +Sorted with compareNumbers: 9,80,700 + +mixedNumericArray: 80,9,700,40,1,5,200 +Sorted without a compare function: 1,200,40,5,700,80,9 +Sorted with compareNumbers: 1,5,9,40,80,200,700 +</pre> + +<h3 id="Example_Sorting_non-ASCII_characters" name="Example:_Sorting_non-ASCII_characters">对非 ASCII 字符排序</h3> + +<p>当排序非 ASCII 字符的字符串(如包含类似 e, é, è, a, ä 等字符的字符串)。一些非英语语言的字符串需要使用 {{jsxref("String.localeCompare")}}。这个函数可以将函数排序到正确的顺序。</p> + +<pre class="brush: js">var items = ['réservé', 'premier', 'cliché', 'communiqué', 'café', 'adieu']; +items.sort(function (a, b) { + return a.localeCompare(b); +}); + +// items is ['adieu', 'café', 'cliché', 'communiqué', 'premier', 'réservé'] +</pre> + +<h3 id="Example_Sorting_maps" name="Example:_Sorting_maps">使用映射改善排序</h3> + +<p><code>compareFunction</code> 可能需要对元素做多次映射以实现排序,尤其当 <code>compareFunction</code> 较为复杂,且元素较多的时候,某些 <code>compareFunction</code> 可能会导致很高的负载。使用 map 辅助排序将会是一个好主意。基本思想是首先将数组中的每个元素比较的实际值取出来,排序后再将数组恢复。</p> + +<pre class="brush: js">// 需要被排序的数组 +var list = ['Delta', 'alpha', 'CHARLIE', 'bravo']; + +// 对需要排序的数字和位置的临时存储 +var mapped = list.map(function(el, i) { + return { index: i, value: el.toLowerCase() }; +}) + +// 按照多个值排序数组 +mapped.sort(function(a, b) { + return +(a.value > b.value) || +(a.value === b.value) - 1; +}); + +// 根据索引得到排序的结果 +var result = mapped.map(function(el){ + return list[el.index]; +}); +</pre> + +<h2 id="Specifications" name="Specifications">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.11', 'Array.prototype.sort')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.sort', 'Array.prototype.sort')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.sort', 'Array.prototype.sort')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.sort")}}</p> +</div> +</div> + +<h2 id="See_also" name="See_also">参考</h2> + +<ul> + <li>{{jsxref("Array.prototype.reverse()")}}</li> + <li>{{jsxref("String.prototype.localeCompare()")}}</li> + <li><a href="https://zhuanlan.zhihu.com/p/55338902">[译] V8引擎中的排序</a></li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/splice/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/splice/index.html new file mode 100644 index 0000000000..2dcb909975 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/splice/index.html @@ -0,0 +1,165 @@ +--- +title: Array.prototype.splice() +slug: Web/JavaScript/Reference/Global_Objects/Array/splice +tags: + - Array + - JavaScript + - 原型 + - 参考 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/splice +--- +<div>{{JSRef}}</div> + +<p><strong><code>splice()</code></strong> 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-splice.html")}}</div> + +<p class="hidden">交互范例的源码储存于 GitHub 仓库。想要参与此项目,可 clone <a href="https://github.com/mdn/interactive-examples">https://github.com/mdn/interactive-examples</a> 并发送 pull request 给我们。</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox"><var>array</var>.splice(<var>start[</var>, <var>deleteCount[</var>, <var>item1[</var>, <var>item2[</var>, <em>...]]]]</em>) +</pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>start</code></dt> + <dd>指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于<code>array.length-n</code>);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。</dd> + <dt><code>deleteCount</code> {{optional_inline}}</dt> + <dd>整数,表示要移除的数组元素的个数。</dd> + <dd>如果 <code>deleteCount</code> 大于 <code>start</code> 之后的元素的总数,则从 <code>start</code> 后面的元素都将被删除(含第 <code>start</code> 位)。</dd> + <dd>如果 <code>deleteCount</code> 被省略了,或者它的值大于等于<code>array.length - start</code>(也就是说,如果它大于或者等于<code>start</code>之后的所有元素的数量),那么<code>start</code>之后数组的所有元素都会被删除。</dd> + <dd>如果 <code>deleteCount</code> 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。</dd> + <dt><code>item1, item2, <em>...</em></code> {{optional_inline}}</dt> + <dd>要添加进数组的元素,从<code><var>start</var></code> 位置开始。如果不指定,则 <code>splice()</code> 将只删除数组元素。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。</p> + +<h2 id="描述">描述</h2> + +<p>如果添加进数组的元素个数不等于被删除的元素个数,数组的长度会发生相应的改变。</p> + +<h2 id="示例">示例</h2> + +<h3 id="从第_2_位开始删除_0_个元素,插入“drum”">从第 2 位开始删除 0 个元素,插入“drum”</h3> + +<pre class="brush: js">var myFish = ["angel", "clown", "mandarin", "sturgeon"]; +var removed = myFish.splice(2, 0, "drum"); + +// 运算后的 myFish: ["angel", "clown", "drum", "mandarin", "sturgeon"] +// 被删除的元素: [], 没有元素被删除 +</pre> + +<h3 id="从第_2_位开始删除_0_个元素,插入“drum”_和_guitar">从第 2 位开始删除 0 个元素,插入“drum” 和 "guitar"</h3> + +<pre class="brush: js">var myFish = ['angel', 'clown', 'mandarin', 'sturgeon']; +var removed = myFish.splice(2, 0, 'drum', 'guitar'); + +// 运算后的 myFish: ["angel", "clown", "drum", "guitar", "mandarin", "sturgeon"] +// 被删除的元素: [], 没有元素被删除 +</pre> + +<h3 id="从第_3_位开始删除_1_个元素">从第 3 位开始删除 1 个元素</h3> + +<pre class="brush: js">var myFish = ['angel', 'clown', 'drum', 'mandarin', 'sturgeon']; +var removed = myFish.splice(3, 1); + +// 运算后的 myFish: ["angel", "clown", "drum", "sturgeon"] +// 被删除的元素: ["mandarin"] +</pre> + +<h3 id="从第_2_位开始删除_1_个元素,插入“trumpet”">从第 2 位开始删除 1 个元素,插入“trumpet”</h3> + +<pre class="brush: js">var myFish = ['angel', 'clown', 'drum', 'sturgeon']; +var removed = myFish.splice(2, 1, "trumpet"); + +// 运算后的 myFish: ["angel", "clown", "trumpet", "sturgeon"] +// 被删除的元素: ["drum"] +</pre> + +<h3 id="从第_0_位开始删除_2_个元素,插入parrot、anemone和blue">从第 0 位开始删除 2 个元素,插入"parrot"、"anemone"和"blue"</h3> + +<pre class="brush: js">var myFish = ['angel', 'clown', 'trumpet', 'sturgeon']; +var removed = myFish.splice(0, 2, 'parrot', 'anemone', 'blue'); + +// 运算后的 myFish: ["parrot", "anemone", "blue", "trumpet", "sturgeon"] +// 被删除的元素: ["angel", "clown"] +</pre> + +<h3 id="从第_2_位开始删除_2_个元素">从第 2 位开始删除 2 个元素</h3> + +<pre class="brush: js">var myFish = ['parrot', 'anemone', 'blue', 'trumpet', 'sturgeon']; +var removed = myFish.splice(myFish.length - 3, 2); + +// 运算后的 myFish: ["parrot", "anemone", "sturgeon"] +// 被删除的元素: ["blue", "trumpet"] +</pre> + +<h3 id="从倒数第_2_位开始删除_1_个元素">从倒数第 2 位开始删除 1 个元素</h3> + +<pre class="brush: js">var myFish = ['angel', 'clown', 'mandarin', 'sturgeon']; +var removed = myFish.splice(-2, 1); + +// 运算后的 myFish: ["angel", "clown", "sturgeon"] +// 被删除的元素: ["mandarin"]</pre> + +<h3 id="从第_2_位开始删除所有元素">从第 2 位开始删除所有元素</h3> + +<pre class="brush: js">var myFish = ['angel', 'clown', 'mandarin', 'sturgeon']; +var removed = myFish.splice(2); + +// 运算后的 myFish: ["angel", "clown"] +// 被删除的元素: ["mandarin", "sturgeon"] +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Initial definition. Implemented in JavaScript 1.2.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.12', 'Array.prototype.splice')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.splice', 'Array.prototype.splice')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.splice', 'Array.prototype.splice')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div class="hidden">此页面中的兼容性表是根据结构化数据生成的。如果您想为数据做出贡献,请查看 <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 并发送 pull request 给我们。</div> + +<p>{{Compat("javascript.builtins.Array.splice")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.push()", "push()")}} / {{jsxref("Array.prototype.pop()", "pop()")}} - 在数组末尾增/删元素;</li> + <li>{{jsxref("Array.prototype.unshift()", "unshift()")}} / {{jsxref("Array.prototype.shift()", "shift()")}} - 在数组首部增/删元素;</li> + <li>{{jsxref("Array.prototype.concat()", "concat()")}} - 把一个(或多个)数组和(或)值与原数组拼接,返回拼接后的数组。</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/tolocalestring/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/tolocalestring/index.html new file mode 100644 index 0000000000..38b9c01c94 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/tolocalestring/index.html @@ -0,0 +1,177 @@ +--- +title: Array.prototype.toLocaleString() +slug: Web/JavaScript/Reference/Global_Objects/Array/toLocaleString +tags: + - Array + - JavaScript + - Method +translation_of: Web/JavaScript/Reference/Global_Objects/Array/toLocaleString +--- +<div>{{JSRef("Global_Objects", "Array")}}</div> + +<p><code><strong>toLocaleString()</strong></code> 返回一个字符串表示数组中的元素。数组中的元素将使用各自的 <code>toLocaleString</code> 方法转成字符串,这些字符串将使用一个特定语言环境的字符串(例如一个逗号 ",")隔开。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-tolocalestring.html")}}</div> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox"><font face="consolas, Liberation Mono, courier, monospace">arr.toLocaleString([locales[,options]]);</font></pre> + +<h3 id="参数"><font face="consolas, Liberation Mono, courier, monospace">参数</font></h3> + +<dl> + <dt><code>locales</code> {{optional_inline}}</dt> + <dd>带有BCP 47语言标记的字符串或字符串数组,关于<code>locales</code>参数的形式与解释,请看{{jsxref("Intl")}}页面。</dd> + <dt><code>options</code> {{optional_inline}}</dt> + <dd>一个可配置属性的对象,对于数字 {{jsxref("Number.prototype.toLocaleString()")}},对于日期{{jsxref("Date.prototype.toLocaleString()")}}.</dd> +</dl> + +<h3 id="返回值"><font face="consolas, Liberation Mono, courier, monospace">返回值</font></h3> + +<p>表示数组元素的字符串。</p> + +<h2 id="示例">示例</h2> + +<h3 id="使用locales和options">使用<code>locales</code>和<code>options</code></h3> + +<p>数组中的元素将会使用各自的 toLocaleString 方法:</p> + +<ul> + <li><code>Object</code>: {{jsxref("Object.prototype.toLocaleString()")}}</li> + <li><code>Number</code>: {{jsxref("Number.prototype.toLocaleString()")}}</li> + <li><code>Date</code>: {{jsxref("Date.prototype.toLocaleString()")}}</li> +</ul> + +<p>总是在<code>prices</code>数组中显示字符串和数字的货币符号:</p> + +<pre class="brush: js">var prices = ['¥7', 500, 8123, 12]; +prices.toLocaleString('ja-JP', { style: 'currency', currency: 'JPY' }); + +// "¥7,¥500,¥8,123,¥12"</pre> + +<p>更多实例请看 {{jsxref("Intl")}},{{jsxref("NumberFormat")}}和{{jsxref("DateTimeFormat")}}页面。</p> + +<h2 id="Polyfill">Polyfill</h2> + +<pre class="brush: js">// https://tc39.github.io/ecma402/#sup-array.prototype.tolocalestring +if (!Array.prototype.toLocaleString) { + Object.defineProperty(Array.prototype, 'toLocaleString', { + value: function(locales, options) { + // 1. Let O be ? ToObject(this value). + if (this == null) { + throw new TypeError('"this" is null or not defined'); + } + + var a = Object(this); + + // 2. Let len be ? ToLength(? Get(A, "length")). + var len = a.length >>> 0; + + // 3. Let separator be the String value for the + // list-separator String appropriate for the + // host environment's current locale (this is + // derived in an implementation-defined way). + // NOTE: In this case, we will use a comma + var separator = ','; + + // 4. If len is zero, return the empty String. + if (len === 0) { + return ''; + } + + // 5. Let firstElement be ? Get(A, "0"). + var firstElement = a[0]; + // 6. If firstElement is undefined or null, then + // a.Let R be the empty String. + // 7. Else, + // a. Let R be ? + // ToString(? + // Invoke( + // firstElement, + // "toLocaleString", + // « locales, options » + // ) + // ) + var r = firstElement == null ? + '' : firstElement.toLocaleString(locales, options); + + // 8. Let k be 1. + var k = 1; + + // 9. Repeat, while k < len + while (k < len) { + // a. Let S be a String value produced by + // concatenating R and separator. + var s = r + separator; + + // b. Let nextElement be ? Get(A, ToString(k)). + var nextElement = a[k]; + + // c. If nextElement is undefined or null, then + // i. Let R be the empty String. + // d. Else, + // i. Let R be ? + // ToString(? + // Invoke( + // nextElement, + // "toLocaleString", + // « locales, options » + // ) + // ) + r = nextElement == null ? + '' : nextElement.toLocaleString(locales, options); + + // e. Let R be a String value produced by + // concatenating S and R. + r = s + r; + + // f. Increase k by 1. + k++; + } + + // 10. Return R. + return r; + } + }); +} +</pre> + +<p>如果你需要支持真正不支持<code><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty">Object.defineProperty</a></code>的JavaScript引擎,最好不要对<code>Array.prototype</code>方法进行填充,因为你不能使它们不可枚举。</p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.tolocalestring', 'Array.prototype.toLocaleString')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td>Initial definition was in ECMAScript 3.</td> + </tr> + <tr> + <td>{{SpecName('ES Int Draft', '#sup-array.prototype.tolocalestring', 'Array.prototype.toLocaleString')}}</td> + <td>{{Spec2('ES Int Draft')}}</td> + <td>This definition supersedes the definition provided in ECMA-262.</td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Array.toLocaleString")}}</p> + +<h2 id="See_also" name="See_also">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.toString()")}}</li> + <li>{{jsxref("Intl")}}</li> + <li>{{jsxref("Object.prototype.toLocaleString()")}}</li> + <li>{{jsxref("Number.prototype.toLocaleString()")}}</li> + <li>{{jsxref("Date.prototype.toLocaleString()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/tosource/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/tosource/index.html new file mode 100644 index 0000000000..7ff8cff304 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/tosource/index.html @@ -0,0 +1,40 @@ +--- +title: Array.prototype.toSource() +slug: Web/JavaScript/Reference/Global_Objects/Array/toSource +translation_of: Web/JavaScript/Reference/Global_Objects/Array/toSource +--- +<p>{{JSRef("Global_Objects", "Array")}}{{Non-standard_header}}</p> + +<h2 id="Summary" name="Summary">概述</h2> + +<p>返回一个字符串,代表该数组的源代码.</p> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox"><code><em>array</em>.toSource()</code></pre> + +<h3 id="Parameters" name="Parameters">参数</h3> + +<p>无</p> + +<h2 id="Description" name="Description">描述</h2> + +<p>在调试时,你可以使用<code>toSource方法</code>来查看一个数组的内容.</p> + +<h2 id="Examples" name="Examples">例子</h2> + +<h3 id="Example:_Examining_the_source_code_of_an_array" name="Example:_Examining_the_source_code_of_an_array">例子: 查看数组的源码</h3> + +<pre class="brush:js">var alpha = new Array("a", "b", "c"); + +alpha.toSource(); //返回["a", "b", "c"]</pre> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<p>{{Compat("javascript.builtins.Array.toSource")}}</p> + +<h2 id="See_also" name="See_also">相关链接</h2> + +<ul> + <li><a href="/zh-CN/docs/JavaScript/Reference/Global_Objects/Array/toString" title="JavaScript/Reference/Global_Objects/Array/toString">Array.toString</a></li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/tostring/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/tostring/index.html new file mode 100644 index 0000000000..9d49798a94 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/tostring/index.html @@ -0,0 +1,80 @@ +--- +title: Array.prototype.toString() +slug: Web/JavaScript/Reference/Global_Objects/Array/toString +tags: + - Array + - JavaScript + - Method +translation_of: Web/JavaScript/Reference/Global_Objects/Array/toString +--- +<div>{{JSRef("Global_Objects", "Array")}}</div> + +<p><code><strong>toString()</strong></code> 返回一个字符串,表示指定的数组及其元素。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-tostring.html")}}</div> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="brush: js">arr.toString() +</pre> + +<h3 id="Parameters" name="Parameters">返回值</h3> + +<p>一个表示指定的数组及其元素的字符串。</p> + +<h2 id="描述">描述</h2> + +<p>{{jsxref("Array")}}对象覆盖了{{jsxref("Object")}}的 <code>toString</code> 方法。对于数组对象,<code>toString</code> 方法连接数组并返回一个字符串,其中包含用逗号分隔的每个数组元素。</p> + +<p>当一个数组被作为文本值或者进行字符串连接操作时,将会自动调用其 <code>toString</code> 方法。</p> + +<h3 id="ECMAScript_5_semantics">ECMAScript 5 semantics</h3> + +<p>从 JavaScript 1.8.5 (<span class="st">Firefox 4</span>) 开始,和 ECMAScript 第5版语义(semantics)一致,<code>toString()</code> 方法是通用的,可被用于任何对象。将调用{{jsxref("Object.prototype.toString()")}},并返回结果值。</p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + <tr> + <td>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.1.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.2', 'Array.prototype.toString')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.tostring', 'Array.prototype.toString')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.tostring', 'Array.prototype.toString')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Array.toString")}}</p> +</div> + +<h2 id="See_Also" name="See_Also">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.join()")}}</li> + <li>{{jsxref("Object.prototype.toSource()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/unobserve/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/unobserve/index.html new file mode 100644 index 0000000000..90678a1081 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/unobserve/index.html @@ -0,0 +1,86 @@ +--- +title: Array.unobserve() +slug: Web/JavaScript/Reference/Global_Objects/Array/unobserve +translation_of: Archive/Web/JavaScript/Array.unobserve +--- +<div>{{JSRef}} {{non-standard_header}}</div> + +<p>Array<strong>.unobserve()方法用来移除</strong>{{jsxref("Array.observe()")}}设置的所有观察者。</p> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox"><code>Array.unobserve(<var>arr</var>, <var>callback</var>)</code></pre> + +<h3 id="参数">参数</h3> + +<dl> + <dt><code>arr</code></dt> + <dd>停止观察的数组。</dd> + <dt> </dt> + <dt><code>callback回调</code></dt> + <dd>需要停止的array <strong>arr</strong>每次改变都会调用的函数引用。</dd> +</dl> + +<h2 id="描述">描述</h2> + +<p><code>Array.unobserve()</code> 方法因为要移除观察者,所以应该在{{jsxref("Array.observe()")}}调用后调用。</p> + +<p>回调函数应该是一个函数的引用并且不能是匿名函数, 因为这个函数需要用来移除前面的观察者, 如果用匿名函数是没有用的,将不能移除任何观察者。</p> + +<h2 id="例子">例子</h2> + +<h3 id="停止观察一个数组">停止观察一个数组</h3> + +<pre class="brush: js">var arr = [1, 2, 3]; + +var observer = function(changes) { + console.log(changes); +} + +Array.observe(arr, observer); + +arr.push(4); +// [{type: "splice", object: <arr>, index: 3, removed:[], addedCount: 1}] + +Array.unobserve(arr, observer); + +arr.pop(); +// The callback wasn't called</pre> + +<h3 id="使用匿名函数">使用匿名函数</h3> + +<pre class="brush: js">var persons = ['Khalid', 'Ahmed', 'Mohammed']; + +Array.observe(persons, function (changes) { + console.log(changes); +}); + +persons.shift(); +// [{type: "splice", object: <arr>, index: 0, removed: [ "Khalid" ], addedCount: 0 }] + +Array.unobserve(persons, function (changes) { + console.log(changes); +}); + +persons.push('Abdullah'); +// [{type: "splice", object: <arr>, index: 2, removed: [], addedCount: 1 }] +// The callback will always be called +</pre> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div> +<div> + + +<p>{{Compat("javascript.builtins.Array.unobserve")}}</p> +</div> +</div> + +<h2 id="相关内容">相关内容</h2> + +<ul> + <li>{{jsxref("Array.observe()")}} {{non-standard_inline}}</li> + <li>{{jsxref("Object.observe()")}} {{non-standard_inline}}</li> + <li>{{jsxref("Object.unobserve()")}} {{non-standard_inline}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/unshift/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/unshift/index.html new file mode 100644 index 0000000000..7b1148813f --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/unshift/index.html @@ -0,0 +1,120 @@ +--- +title: Array.prototype.unshift() +slug: Web/JavaScript/Reference/Global_Objects/Array/unshift +tags: + - Array + - JavaScript + - Method + - 原型 + - 参考资料 + - 数组 + - 方法 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/unshift +--- +<p>{{JSRef}}</p> + +<p><strong><code>unshift()</code></strong> 方法将一个或多个元素添加到数组的<strong>开头</strong>,并返回该数组的<strong>新长度(该</strong>方法修改原有数组<strong>)</strong>。</p> + +<div>{{EmbedInteractiveExample("pages/js/array-unshift.html")}}</div> + +<h2 id="Syntax" name="Syntax">语法</h2> + +<pre class="syntaxbox">arr.unshift(element1, ..., elementN) +</pre> + +<h3 id="Parameters" name="Parameters">参数列表</h3> + +<dl> + <dt><code>elementN</code></dt> + <dd>要添加到数组开头的元素或多个元素。</dd> +</dl> + +<h3 id="返回值">返回值</h3> + +<p>当一个对象调用该方法时,返回其 {{jsxref("Array.length", "length")}} 属性值。</p> + +<dl> +</dl> + +<h2 id="Description" name="Description">描述</h2> + +<p><code>unshift</code> 方法会在调用它的类数组对象的开始位置插入给定的参数。</p> + +<p><code>unshift</code> 特意被设计成具有通用性;这个方法能够通过 {{jsxref("Function.call", "call")}} 或 {{jsxref("Function.apply", "apply")}} 方法作用于类数组对象上。<span style="line-height: inherit;">不过对于没有 length 属性(代表从0开始的一系列连续的数字属性的最后一个)的对象,调用该方法可能没有任何意义。</span></p> + +<p>注意, 如果传入多个参数,它们会被以块的形式插入到对象的开始位置,它们的顺序和被作为参数传入时的顺序一致。 于是,传入多个参数调用一次 <code>unshift</code> ,和传入一个参数调用多次 <code>unshift</code> (例如,循环调用),它们将得到不同的结果。例如:</p> + +<pre class="syntaxbox">let arr = [4,5,6]; +arr.unshift(1,2,3); +console.log(arr); // [<strong>1, 2, 3</strong>, 4, 5, 6] + +arr = [4,5,6]; // 重置数组 +arr.unshift(1); +arr.unshift(2); +arr.unshift(3); +console.log(arr); // [<strong>3, 2, 1</strong>, 4, 5, 6] +</pre> + +<h2 id="示例">示例</h2> + +<pre class="brush: js">let arr = [1, 2]; + +arr.unshift(0); // result of the call is 3, which is the new array length +// arr is [0, 1, 2] + +arr.unshift(-2, -1); // the new array length is 5 +// arr is [-2, -1, 0, 1, 2] + +arr.unshift([-4, -3]); // the new array length is 6 +// arr is [[-4, -3], -2, -1, 0, 1, 2] + +arr.unshift([-7, -6], [-5]); // the new array length is 8 +// arr is [ [-7, -6], [-5], [-4, -3], -2, -1, 0, 1, 2 ] +</pre> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范</th> + <th scope="col">状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Initial definition. Implemented in JavaScript 1.2.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.13', 'Array.prototype.unshift')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.unshift', 'Array.prototype.unshift')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.unshift', 'Array.prototype.unshift')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + +<div class="hidden">兼容性表是使用结构化数据生成的. 如果您希望为此数据做贡献, 请检出(check out) <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> 同时向我们提交一个pull request.</div> + +<p>{{Compat("javascript.builtins.Array.unshift")}}</p> + +<h2 id="参见">参见</h2> + +<ul> + <li>{{jsxref("Array.prototype.push()")}}</li> + <li>{{jsxref("Array.prototype.pop()")}}</li> + <li>{{jsxref("Array.prototype.shift()")}}</li> + <li>{{jsxref("Array.prototype.concat()")}}</li> +</ul> diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/values/index.html b/files/zh-cn/web/javascript/reference/global_objects/array/values/index.html new file mode 100644 index 0000000000..cf9b1c7c82 --- /dev/null +++ b/files/zh-cn/web/javascript/reference/global_objects/array/values/index.html @@ -0,0 +1,125 @@ +--- +title: Array.prototype.values() +slug: Web/JavaScript/Reference/Global_Objects/Array/values +tags: + - Array + - ECMAScript 2015 + - Iterator + - JavaScript + - Prototype + - 数组 + - 方法 + - 迭代 +translation_of: Web/JavaScript/Reference/Global_Objects/Array/values +--- +<div>{{JSRef}}</div> + +<p><strong><code>values()</code></strong> 方法返回一个新的 <strong><code>Array Iterator</code></strong> 对象,该对象包含数组每个索引的值</p> + +<div>{{EmbedInteractiveExample("pages/js/array-values.html")}}</div> + +<h2 id="语法">语法</h2> + +<pre class="syntaxbox notranslate"><var>arr</var>.values()</pre> + +<h3 id="返回值">返回值</h3> + +<p>一个新的 {{jsxref("Array")}} 迭代对象。</p> + +<h2 id="示例">示例</h2> + +<h3 id="使用_for...of_循环进行迭代">使用 <code>for...of</code> 循环进行迭代</h3> + +<pre class="brush: js notranslate">let arr = ['w', 'y', 'k', 'o', 'p']; +let eArr = arr.values(); + +for (let letter of eArr) { + console.log(letter); +} //"w" "y "k" "o" "p"</pre> + +<p><strong>Array.prototype.values</strong> 是 <strong>Array.prototype[Symbol.iterator] </strong>的默认实现。</p> + +<pre class="notranslate">Array.prototype.values === Array.prototype[Symbol.iterator] // true </pre> + +<h3 id="使用_.next_迭代">使用 <code>.next()</code> 迭代</h3> + +<pre class="notranslate">var arr = ['a', 'b', 'c', 'd', 'e']; +var iterator = arr.values(); +iterator.next(); // Object { value: "a", done: false } +iterator.next().value; // "b" +iterator.next()["value"]; // "c" +iterator.next(); // Object { value: "d", done: false } +iterator.next(); // Object { value: "e", done: false } +iterator.next(); // Object { value: undefined, done: true } +iteraroe.next().value; // undefined</pre> + +<div class="blockIndicator warning"> +<p>一次性:数组迭代器是一次性的,或者说临时对象</p> +</div> + +<p>例子:</p> + +<pre class="notranslate">var arr = ['a', 'b', 'c', 'd', 'e']; + var iterator = arr.values(); + for (let letter of iterator) { + console.log(letter); +} //"a" "b" "c" "d" +for (let letter of iterator) { +console.log(letter); +} // undefined</pre> + +<p><strong>解释:</strong> 当 <code>next().done=true</code> 或 <code>currentIndex>length</code> 时, <code>for..of</code> 循环结束。参见 <a href="/en-US/docs/Web/JavaScript/Reference/Iteration_protocols">Iteration protocols</a> 。</p> + +<p><strong>值</strong>: 数组迭代器中存储的是原数组的地址,而不是数组元素值。</p> + +<pre class="notranslate">var arr = ['a', 'b', 'c', 'd', 'e']; +var iterator = arr.values(); +console.log(iterator); // Array Iterator { } +iterator.next().value; // "a" +arr[1] = 'n'; +iterator.next().value; // "n" +</pre> + +<div class="blockIndicator note"> +<p>如果数组中元素改变,那么迭代器的值也会改变</p> +</div> + +<p class="hidden"><strong>TODO</strong>: please write about why we need it, use cases.</p> + +<h2 id="规范">规范</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">规范名称</th> + <th scope="col">规范状态</th> + <th scope="col">备注</th> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.values', 'Array.prototype.values')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>首次定义</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-array.prototype.values', 'Array.prototype.values')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="浏览器兼容性">浏览器兼容性</h2> + + + +<p>{{Compat("javascript.builtins.Array.values")}}</p> + +<h2 id="相关链接">相关链接</h2> + +<ul> + <li>{{jsxref("Array.prototype.keys()")}}</li> + <li>{{jsxref("Array.prototype.entries()")}}</li> + <li>{{jsxref("Array.prototype.forEach()")}}</li> + <li>{{jsxref("Array.prototype.every()")}}</li> + <li>{{jsxref("Array.prototype.some()")}}</li> +</ul> |