aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/global_objects/array/find/index.html
blob: ee5ad032da93cd3ff8a88bbd764e4eaa198973e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
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">语法</h2>

<pre class="syntaxbox"><code><em>arr</em>.find(<em>callback</em>[, <em>thisArg</em>])</code></pre>

<h3 id="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">描述</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 &lt;= Math.sqrt(element)) {
    if (element % start++ &lt; 1) {
      return false;
    }
  }
  return element &gt; 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">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 &gt;&gt;&gt; 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 &lt; len
      while (k &lt; 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">相关链接</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>