From 5df54a59e07af2ac82a01e8e3983589982d56b9f Mon Sep 17 00:00:00 2001 From: YangFong Date: Tue, 6 Sep 2022 15:18:19 +0800 Subject: [PATCH 1/7] docs: update filter() --- .../global_objects/array/filter/index.md | 185 +++++++++--------- 1 file changed, 97 insertions(+), 88 deletions(-) diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md index 40d03d43671aad..8561cb6ea2ea73 100644 --- a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md +++ b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md @@ -4,31 +4,44 @@ slug: Web/JavaScript/Reference/Global_Objects/Array/filter --- {{JSRef}} -**`filter()`** 方法创建一个新数组,其包含通过所提供函数实现的测试的所有元素。 +**`filter()`** 方法创建给定数组一部分的[浅拷贝](/en-US/docs/Glossary/Shallow_copy),其包含通过所提供函数实现的测试的所有元素。 {{EmbedInteractiveExample("pages/js/array-filter.html")}} ## 语法 -```plain -var newArray = arr.filter(callback(element[, index[, array]])[, thisArg]) +```js +// 箭头函数 +filter((element) => { /* … */ } ) +filter((element, index) => { /* … */ } ) +filter((element, index, array) => { /* … */ } ) + +// 回调函数 +filter(callbackFn) +filter(callbackFn, thisArg) + +// 内联回调函数 +filter(function(element) { /* … */ }) +filter(function(element, index) { /* … */ }) +filter(function(element, index, array){ /* … */ }) +filter(function(element, index, array) { /* … */ }, thisArg) ``` ### 参数 -- `callback` +- `callbackFn` - - : 用来测试数组的每个元素的函数。返回 `true` 表示该元素通过测试,保留该元素,`false` 则不保留。它接受以下三个参数: + - : 用来测试数组中每个元素的函数。返回 `true` 表示该元素通过测试,保留该元素,`false` 则不保留。它接受以下三个参数: - `element` - : 数组中当前正在处理的元素。 - - `index`{{optional_inline}} + - `index` - : 正在处理的元素在数组中的索引。 - - `array`{{optional_inline}} - - : 调用了 `filter` 的数组本身。 + - `array` + - : 调用了 `filter()` 的数组本身。 - `thisArg`{{optional_inline}} - - : 执行 `callback` 时,用于 `this` 的值。 + - : 执行 `callbackFn` 时,用于 `this` 的值。 ### 返回值 @@ -36,69 +49,84 @@ var newArray = arr.filter(callback(element[, index[, array]])[, thisArg]) ## 描述 -`filter` 为数组中的每个元素调用一次 `callback` 函数,并利用所有使得 `callback` 返回 true 或[等价于 true 的值](/zh-CN/docs/Glossary/Truthy)的元素创建一个新数组。`callback` 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 `callback` 测试的元素会被跳过,不会被包含在新数组中。 +`filter()` 为数组中的每个元素调用一次 `callbackFn` 函数,并利用所有使得 `callbackFn` 返回 true 或[等价于 true 的值](/zh-CN/docs/Glossary/Truthy)的元素创建一个新数组。`callbackFn` 只会在已经赋值的索引上被调用,对于那些已经被删除或者从未被赋值的索引不会被调用。那些没有通过 `callbackFn` 测试的元素会被跳过,不会被包含在新数组中。 -`callback` 被调用时传入三个参数: +`callbackFn` 被调用时传入三个参数: 1. 元素的值 2. 元素的索引 3. 被遍历的数组本身 -如果为 `filter` 提供一个 `thisArg` 参数,则它会被作为 `callback` 被调用时的 `this` 值。否则,`callback` 的 `this` 值在非严格模式下将是全局对象,严格模式下为 `undefined`。`callback` 函数最终观察到的 `this` 值是根据[通常函数所看到的 "this"的规则](/zh-CN/docs/Web/JavaScript/Reference/Operators/this)确定的。 +如果为 `filter()` 提供一个 `thisArg` 参数,则它会被作为 `callbackFn` 被调用时的 `this` 值。否则,`callbackFn` 的 `this` 值在非严格模式下将是全局对象,严格模式下为 `undefined`。`callbackFn` 函数最终观察到的 `this` 值是根据[通常函数所看到的 "this" 的规则](/zh-CN/docs/Web/JavaScript/Reference/Operators/this)确定的。 -`filter` 不会改变原数组,它返回过滤后的新数组。 +`filter()` 不会改变原数组,它返回过滤后的新数组。 -`filter` 遍历的元素范围在第一次调用 `callback` 之前就已经确定了。在调用 `filter` 之后被添加到数组中的元素不会被 `filter` 遍历到。如果已经存在的元素被改变了,则他们传入 `callback` 的值是 `filter` 遍历到它们那一刻的值。被删除或从来未被赋值的元素不会被遍历到。 +`filter()` 遍历的元素范围在第一次调用 `callbackFn` 之前就已经确定了。在调用 `filter()` 之后被添加到数组中的元素不会被 `filter()` 遍历到。如果已经存在的元素被改变了,则他们传入 `callbackFn` 的值是 `filter()` 遍历到它们那一刻的值。被删除或从未赋值的元素不会被遍历到。 ## 示例 ### 筛选排除所有较小的值 -下例使用 `filter` 创建了一个新数组,该数组的元素由原数组中值大于 10 的元素组成。 +下例使用 `filter()` 创建了一个新数组,该数组的元素由原数组中值大于 `10` 的元素组成。 ```js function isBigEnough(element) { return element >= 10; } -var filtered = [12, 5, 8, 130, 44].filter(isBigEnough); +const filtered = [12, 5, 8, 130, 44].filter(isBigEnough); // filtered is [12, 130, 44] ``` +### 找出数组中所有的素数 + +下面的例子返回数组中的所有质数: + +```js +const array = [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]; + +function isPrime(num) { + for (let i = 2; num > i; i++) { + if (num % i === 0) { + return false; + } + } + return num > 1; +} + +console.log(array.filter(isPrime)); // [2, 3, 5, 7, 11, 13] +``` + ### 过滤 JSON 中的无效条目 以下示例使用 `filter()` 创建具有非零 `id` 的元素的 json。 ```js -var arr = [ +const arr = [ { id: 15 }, { id: -1 }, { id: 0 }, { id: 3 }, { id: 12.2 }, - { }, + {}, { id: null }, { id: NaN }, - { id: 'undefined' } + { id: 'undefined' }, ]; -var invalidEntries = 0; - -function isNumber(obj) { - return obj !== undefined && typeof(obj) === 'number' && !isNaN(obj); -} +let invalidEntries = 0; function filterByID(item) { - if (isNumber(item.id) && item.id !== 0) { + if (Number.isFinite(item.id) && item.id !== 0) { return true; } invalidEntries++; return false; } -var arrByID = arr.filter(filterByID); +const 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); @@ -109,79 +137,58 @@ console.log('Number of Invalid Entries = ', invalidEntries); 下例使用 `filter()` 根据搜索条件来过滤数组内容。 -```js -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'] -``` - -#### ES2015 实现 - ```js 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 - ); +function filterItems(arr, query) { + return arr.filter((el) => el.toLowerCase().includes(query.toLowerCase())); } -console.log(filterItems('ap')); // ['apple', 'grapes'] -console.log(filterItems('an')); // ['banana', 'mango', 'orange'] +console.log(filterItems(fruits, 'ap')); // ['apple', 'grapes'] +console.log(filterItems(fruits, 'an')); // ['banana', 'mango', 'orange'] ``` -## Polyfill +### 影响初始数组(修改,追加和删除) -`filter` 被添加到 ECMA-262 标准第 5 版中,因此在某些实现环境中不被支持。可以把下面的代码插入到脚本的开头来解决此问题,该代码允许在那些没有原生支持 `filter` 的实现环境中使用它。该算法是 ECMA-262 第 5 版中指定的算法,假定 `fn.call` 等价于 {{jsxref("Function.prototype.call")}} 的初始值,且 {{jsxref("Array.prototype.push")}} 拥有它的初始值。 +下面的示例测试在修改数组时 `filter()` 方法的行为。 ```js -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; - }; -} +// 修改每个单词 +let words = ['spray', 'limit', 'exuberant', 'destruction', 'elite', 'present']; + +const modifiedWords = words.filter((word, index, arr) => { + arr[index + 1] += ' extra'; + return word.length < 6; +}); + +console.log(modifiedWords); +// 注意,在长度为6以下有三个单词,但是由于它们已经被修改,所以返回一个单词 +// ["spray"] + +// 添加新单词 +words = ['spray', 'limit', 'exuberant', 'destruction', 'elite', 'present']; +const appendedWords = words.filter((word, index, arr) => { + arr.push('new'); + return word.length < 6; +}) + +console.log(appendedWords); +// 只有三个符合条件,即使 `words`本身现在有更多字符长度小于 6 的单词 +// ["spray" ,"limit" ,"elite"] + +// 删除单词 +words = ['spray', 'limit', 'exuberant', 'destruction', 'elite', 'present']; +const deleteWords = words.filter((word, index, arr) => { + arr.pop(); + return word.length < 6; +}) + +console.log(deleteWords); +// 注意,'elite' 也没有获得,因为它在过滤器达到之前就已经从 'words' 弹出了 +// ["spray" ,"limit"] ``` ## 规范 @@ -194,7 +201,9 @@ if (!Array.prototype.filter){ ## 参见 +- [Polyfill of `Array.prototype.filter` in `core-js`](https://github.com/zloirock/core-js#ecmascript-array) - {{jsxref("Array.prototype.forEach()")}} - {{jsxref("Array.prototype.every()")}} - {{jsxref("Array.prototype.some()")}} - {{jsxref("Array.prototype.reduce()")}} +- {{jsxref("Array.prototype.find()")}} From af89a2f15093e8957586d36380f31c79ece0b2e1 Mon Sep 17 00:00:00 2001 From: YangQi Date: Tue, 6 Sep 2022 15:40:39 +0800 Subject: [PATCH 2/7] Update files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md Co-authored-by: A1lo --- .../javascript/reference/global_objects/array/filter/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md index 8561cb6ea2ea73..9d738cc1216bc6 100644 --- a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md +++ b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md @@ -57,7 +57,7 @@ filter(function(element, index, array) { /* … */ }, thisArg) 2. 元素的索引 3. 被遍历的数组本身 -如果为 `filter()` 提供一个 `thisArg` 参数,则它会被作为 `callbackFn` 被调用时的 `this` 值。否则,`callbackFn` 的 `this` 值在非严格模式下将是全局对象,严格模式下为 `undefined`。`callbackFn` 函数最终观察到的 `this` 值是根据[通常函数所看到的 "this" 的规则](/zh-CN/docs/Web/JavaScript/Reference/Operators/this)确定的。 +如果为 `filter()` 提供一个 `thisArg` 参数,则它会被作为 `callbackFn` 被调用时的 `this` 值。否则,`callbackFn` 的 `this` 值在非严格模式下将是全局对象,严格模式下为 `undefined`。`callbackFn` 函数最终观察到的 `this` 值是根据[通常函数所看到的 `this` 的规则](/zh-CN/docs/Web/JavaScript/Reference/Operators/this)确定的。 `filter()` 不会改变原数组,它返回过滤后的新数组。 From 97fe7e9b36bb305a2943908beb34ad983081877a Mon Sep 17 00:00:00 2001 From: YangQi Date: Tue, 6 Sep 2022 15:40:51 +0800 Subject: [PATCH 3/7] Update files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md Co-authored-by: A1lo --- .../javascript/reference/global_objects/array/filter/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md index 9d738cc1216bc6..765ed883090762 100644 --- a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md +++ b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md @@ -141,7 +141,7 @@ console.log('Number of Invalid Entries = ', invalidEntries); const fruits = ['apple', 'banana', 'grapes', 'mango', 'orange']; /** - * 根据搜索条件(查询)筛选数组项 + * 根据搜索条件(查询)筛选数组项 */ function filterItems(arr, query) { return arr.filter((el) => el.toLowerCase().includes(query.toLowerCase())); From 3ef2f167ed61a4218457de9156826ed3fa172f35 Mon Sep 17 00:00:00 2001 From: YangQi Date: Tue, 6 Sep 2022 15:41:10 +0800 Subject: [PATCH 4/7] Update files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md Co-authored-by: A1lo --- .../javascript/reference/global_objects/array/filter/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md index 765ed883090762..85a9fc8bda063a 100644 --- a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md +++ b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md @@ -151,7 +151,7 @@ console.log(filterItems(fruits, 'ap')); // ['apple', 'grapes'] console.log(filterItems(fruits, 'an')); // ['banana', 'mango', 'orange'] ``` -### 影响初始数组(修改,追加和删除) +### 影响初始数组(修改、追加和删除) 下面的示例测试在修改数组时 `filter()` 方法的行为。 From cde13a4f878c3c25a2ec30da2beaf901e67b73cb Mon Sep 17 00:00:00 2001 From: YangQi Date: Tue, 6 Sep 2022 15:49:35 +0800 Subject: [PATCH 5/7] Update files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md Co-authored-by: A1lo --- .../javascript/reference/global_objects/array/filter/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md index 85a9fc8bda063a..e999985ac3f206 100644 --- a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md +++ b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md @@ -4,7 +4,7 @@ slug: Web/JavaScript/Reference/Global_Objects/Array/filter --- {{JSRef}} -**`filter()`** 方法创建给定数组一部分的[浅拷贝](/en-US/docs/Glossary/Shallow_copy),其包含通过所提供函数实现的测试的所有元素。 +**`filter()`** 方法创建给定数组一部分的[浅拷贝](/zh-CN/docs/Glossary/Shallow_copy),其包含通过所提供函数实现的测试的所有元素。 {{EmbedInteractiveExample("pages/js/array-filter.html")}} From e2d058617d5fe3771a923d0a1d6714571c1e3748 Mon Sep 17 00:00:00 2001 From: YangFong Date: Tue, 6 Sep 2022 16:10:52 +0800 Subject: [PATCH 6/7] Update index.md --- .../reference/global_objects/array/filter/index.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md index e999985ac3f206..8c90e603090e54 100644 --- a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md +++ b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md @@ -59,9 +59,11 @@ filter(function(element, index, array) { /* … */ }, thisArg) 如果为 `filter()` 提供一个 `thisArg` 参数,则它会被作为 `callbackFn` 被调用时的 `this` 值。否则,`callbackFn` 的 `this` 值在非严格模式下将是全局对象,严格模式下为 `undefined`。`callbackFn` 函数最终观察到的 `this` 值是根据[通常函数所看到的 `this` 的规则](/zh-CN/docs/Web/JavaScript/Reference/Operators/this)确定的。 -`filter()` 不会改变原数组,它返回过滤后的新数组。 +`filter()` 不会改变原数组。 -`filter()` 遍历的元素范围在第一次调用 `callbackFn` 之前就已经确定了。在调用 `filter()` 之后被添加到数组中的元素不会被 `filter()` 遍历到。如果已经存在的元素被改变了,则他们传入 `callbackFn` 的值是 `filter()` 遍历到它们那一刻的值。被删除或从未赋值的元素不会被遍历到。 +`filter()` 遍历的元素范围在第一次调用 `callbackFn` 之前就已经确定了。修改已经访问过或遍历范围之外的元素,将不会被 `callbackFn` 访问。如果以相同的方式删除数组中的现有元素,则不会访问它们。 + +> **警告:** 在上一段中描述的并发修改通常会导致难以理解的代码,通常应该避免(特殊情况除外)。 ## 示例 @@ -70,9 +72,10 @@ filter(function(element, index, array) { /* … */ }, thisArg) 下例使用 `filter()` 创建了一个新数组,该数组的元素由原数组中值大于 `10` 的元素组成。 ```js -function isBigEnough(element) { - return element >= 10; +function isBigEnough(value) { + return value >= 10; } + const filtered = [12, 5, 8, 130, 44].filter(isBigEnough); // filtered is [12, 130, 44] ``` From 513c9aee940deacc6d9a0064288af5636c8d275c Mon Sep 17 00:00:00 2001 From: YangQi Date: Tue, 6 Sep 2022 17:18:32 +0800 Subject: [PATCH 7/7] Update files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md Co-authored-by: A1lo --- .../javascript/reference/global_objects/array/filter/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md index 8c90e603090e54..2052e5c1d6abe5 100644 --- a/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md +++ b/files/zh-cn/web/javascript/reference/global_objects/array/filter/index.md @@ -61,7 +61,7 @@ filter(function(element, index, array) { /* … */ }, thisArg) `filter()` 不会改变原数组。 -`filter()` 遍历的元素范围在第一次调用 `callbackFn` 之前就已经确定了。修改已经访问过或遍历范围之外的元素,将不会被 `callbackFn` 访问。如果以相同的方式删除数组中的现有元素,则不会访问它们。 +`filter()` 遍历的元素范围在第一次调用 `callbackFn` 之前就已经确定了。修改已经访问过的或在确定的范围之外创建的元素,将不会被 `callbackFn` 访问。如果以相同的方式删除数组中的现有元素,则不会访问它们。 > **警告:** 在上一段中描述的并发修改通常会导致难以理解的代码,通常应该避免(特殊情况除外)。