Array.prototype.filter()

Метод filter() создаёт новый массив со всеми элементами, прошедшими проверку, задаваемую в передаваемой функции.

Синтаксис

let newArray = arr.filter(callback(element[, index, [array]])[, thisArg])

Параметры

callback
Функция, которая будет вызвана для каждого элемента массива. Если функция возвращает true, то элемент остаётся в массиве, если false, то удаляется.
В функцию будет передано три аргумента:
element
Текущий обрабатываемый элемент в массиве.
indexНеобязательный
Индекс текущего обрабатываемого элемента в массиве.
arrayНеобязательный
Массив, по которому осуществляется проход.
thisArg Необязательный
Значение, используемое в качестве this при вызове функции callback.

Возвращаемое значение

Вернётся новый массив с элементами, которые проходят тест, то есть callback вернёт true. Если ни один элемент не пройдёт тест, то будет возвращён пустой массив.

Описание

Метод filter() вызывает переданную функцию callback один раз для каждого элемента, присутствующего в массиве, и конструирует новый массив со всеми значениями, для которых функция callback вернула true или значение, становящееся true при приведении в boolean. Функция callback вызывается только для индексов массива, имеющих присвоенные значения; она не вызывается для индексов, которые были удалены или которым значения никогда не присваивались. Элементы массива, не прошедшие проверку функцией callback, просто пропускаются и не включаются в новый массив.

Функция callback вызывается с тремя аргументами:

  1. значение элемента;
  2. индекс элемента;
  3. массив, по которому осуществляется проход.

Если в метод filter() был передан параметр thisArg, при вызове callback он будет использоваться в качестве значения this. В противном случае, в качестве значения this будет использоваться значение undefined. В конечном итоге, значение this, наблюдаемое из функции callback, определяется согласно обычным правилам определения this, видимого из функции.

Метод filter() не изменяет массив, для которого он был вызван.

Диапазон элементов, обрабатываемых методом filter(), устанавливается до первого вызова функции callback. Элементы, добавленные в массив после начала выполнения метода filter(), не будут посещены функцией callback. Если существующие элементы массива изменятся, значения, переданные в функцию callback, будут значениями на тот момент времени, когда метод filter() посетит их; удалённые элементы посещены не будут.

Примеры

Отфильтровывание всех маленьких значений

Следующий пример использует filter() для создания отфильтрованного массива, все элементы которого больше или равны 10, а все меньшие 10 удалены.

function isBigEnough(value) {
  return value >= 10;
}

let filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// массив filtered равен [12, 130, 44]

Найти все простые числа в массиве

Следующий пример возвращает все простые числа в массиве:

let array = [4, 6, 8, 9, 12, 53, -17, 2, 5, 7, 31, 97, -1, 17];

function isPrime(num) {
    if (num <= 1)
        return false;
    else if (num === 2)
        return true;
    else {
        for (let i = 2; i < num; i++)
            if (num % i === 0)
                return false;
        return true;
    }
}

console.log(array.filter(isPrime));   // [53, 2, 5, 7, 31, 97, 17]

Фильтрация неверных записей в JSON

В следующем примере метод filter() используется для создания отфильтрованного объекта JSON, все элементы которого содержат ненулевое числовое поле id.

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('Отфильтрованный массив\n', arrByID);
// Filtered Array
// [{ id: 15 }, { id: -1 }, { id: 3 }, { id: 12.2 }]

console.log('Количество ошибочных записей = ', invalidEntries);
// Number of Invalid Entries = 5

Поиск в массиве

В следующем примере filter() используется для фильтрации содержимого массива на основе входных данных.

var fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];

/**
 * Элементы массива фильтруется на основе критериев поиска (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 реализация

const fruits = ['apple', 'banana', 'grapes', 'mango', 'orange'];

/**
 * Элементы массива фильтруется на основе критериев поиска (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']

Влияние на начальный массив (изменение, добавление и удаление)

В следующих примерах проверяется поведение метода filter при изменении массива.

// Изменение всех элементов
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` до того,
// как filter смог получить его: ['spray', 'limit']

Полифилл

Метод filter() был добавлен к стандарту ECMA-262 в 5-м издании; поэтому он может отсутствовать в других реализациях стандарта. Вы можете работать с ним, добавив следующий код в начало ваших скриптов, он позволяет использовать filter() в реализациях, которые не поддерживают этот метод. Этот алгоритм является точно тем, что описан в ECMA-262 5-го издания; он предполагает, что fn.call вычисляется в оригинальное значение Function.prototype.call() и что Array.prototype.push() содержит своё оригинальное значение.

if (!Array.prototype.filter) {
  Array.prototype.filter = function(fun/*, thisArg*/) {
    'use strict';

    if (this === void 0 || this === null) {
      throw new TypeError();
    }

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== 'function') {
      throw new TypeError();
    }

    var res = [];
    var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
    for (var i = 0; i < len; i++) {
      if (i in t) {
        var val = t[i];

        // ПРИМЕЧАНИЕ: Технически, здесь должен быть Object.defineProperty на
        //             следующий индекс, поскольку push может зависеть от
        //             свойств на Object.prototype и Array.prototype.
        //             Но этот метод новый и коллизии должны быть редкими,
        //             так что используем более совместимую альтернативу.
        if (fun.call(thisArg, val, i, t)) {
          res.push(val);
        }
      }
    }

    return res;
  };
}

Спецификации

Спецификация Статус Комментарии
ECMAScript 5.1 (ECMA-262)
Определение 'Array.prototype.filter' в этой спецификации.
Стандарт Изначальное определение. Реализована в JavaScript 1.6.
ECMAScript 2015 (6th Edition, ECMA-262)
Определение 'Array.prototype.filter' в этой спецификации.
Стандарт
ECMAScript (ECMA-262)
Определение 'Array.prototype.filter' в этой спецификации.
Живой стандарт

Совместимость с браузерами

Update compatibility data on GitHub
КомпьютерыМобильныеServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome для AndroidFirefox для AndroidOpera для AndroidSafari on iOSSamsung InternetNode.js
filterChrome Полная поддержка 1Edge Полная поддержка 12Firefox Полная поддержка 1.5IE Полная поддержка 9Opera Полная поддержка 9.5Safari Полная поддержка 3WebView Android Полная поддержка ≤37Chrome Android Полная поддержка 18Firefox Android Полная поддержка 4Opera Android Полная поддержка 10.1Safari iOS Полная поддержка 1Samsung Internet Android Полная поддержка 1.0nodejs Полная поддержка 0.1.100

Легенда

Полная поддержка  
Полная поддержка

Смотрите также