Array.prototype.filter()
filter()
方法會建立一個經指定之函式運算後,由原陣列中通過該函式檢驗之元素所構成的新陣列。
嘗試一下
ES6 版本
js
const words = [
"spray",
"limit",
"elite",
"exuberant",
"destruction",
"present",
"happy",
];
let longWords = words.filter((word) => word.length > 6);
// Filtered array longWords is ["exuberant", "destruction", "present"]
語法
var newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
參數
回傳值
一個元素為通過回呼函式檢驗的新陣列。
描述
filter()
會將所有陣列中的元素分別傳入一次至 callback
函式當中,並將所有傳入此回呼函式並得到回傳值為 Truthy (en-US) 的元素建構成一個新的陣列。callback
函式只會於陣列目前迭代之索引有指派值時被呼叫,回呼函式不會在該陣列索引已被刪除或從未被賦值時被調用。原始陣列中沒有通過 callback
檢驗的元素會被簡單的跳過,且不會被包含在新建立的陣列中。
callback
函式於被調用時會傳入三個參數:
- 元素值
- 元素之索引
- 被迭代的陣列物件
若有提供 thisArg
參數予 filter
方法,thisArg
將會被當作回呼函式的 this
值,否則 this
會是 undefined
。callback
的最終 this
值是依據函式的 this
規則來決定。
filter()
不會修改呼叫它的原始陣列。
由 filter()
方法所回傳之新陣列的範圍,於 callback
函式第一次被調用之前就已經被設定。而在呼叫 filter()
之後才加至原始陣列中的元素,將不會傳入 callback
當中。假如原始陣列中元素的值改變或被刪除了,則 callback
得到此元素的值將會是 filter()
傳入元素當下的值。而被刪除的原始陣列元素並不會被迭代到。
範例
過濾所有的小數字
以下範例會用 filter()
建立一個把所有小於 10 的元素都移掉的陣列。
js
function isBigEnough(value) {
return value >= 10;
}
var filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]
從 JSON 過濾無效的項目
以下範例會用 filter()
建立一個把非零 numeric id
的元素都過濾掉的的 JSON。
js
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)) {
return true;
}
invalidEntries++;
return false;
}
var arrByID = arr.filter(filterByID);
console.log("過濾好的陣列\n", arrByID);
// 過濾好的陣列
// [{ id: 15 }, { id: -1 }, { id: 0 }, { id: 3 }, { id: 12.2 }]
console.log("無效的元素數量 = ", invalidEntries);
// 無效的元素數量 = 4
在陣列中搜尋
下面範例使用 filter()
去過濾符合搜尋條件的陣列內容。
js
var fruits = ["apple", "banana", "grapes", "mango", "orange"];
/**
* 陣列透過搜尋條件(查詢)過濾物件
*/
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"];
/**
* 陣列透過搜尋條件(查詢)過濾物件
*/
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']
Polyfill
filter()
在 ECMA-262 第五版時被納入標準;它也許不會出現在該標準的所有實作引擎之中。你可以在你的腳本最前面加入下面的程式碼作為替代方案,讓不支援 filter()
的 ECMA-262 實作引擎能夠使用它。假設 fn.call
是採用 Function.prototype.bind()
的原始值,這個演算法完全和 ECMA-262 第五版定義的規格相同。
js
if (!Array.prototype.filter)
Array.prototype.filter = function (func, thisArg) {
"use strict";
if (!(typeof func === "Function" && this)) throw new TypeError();
var len = this.length >>> 0,
res = new Array(len), // 預先配置陣列
c = 0,
i = -1;
if (thisArg === undefined)
while (++i !== len)
// 確認物件的鍵值i是否有被設置
if (i in this)
if (func(t[i], i, t)) res[c++] = t[i];
else
while (++i !== len)
// 確認物件的鍵值i是否有被設置
if (i in this)
if (func.call(thisArg, t[i], i, t)) res[c++] = t[i];
res.length = c; // 將陣列縮至適當大小
return res;
};
規範
Specification |
---|
ECMAScript Language Specification # sec-array.prototype.filter |
瀏覽器相容性
BCD tables only load in the browser