Подтвердить что ты не робот

Как фильтровать объект с помощью Array.prototype.filter?

Учитывая

var arr = [1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]]

мы можем фильтровать числовые элементы в массиве arr с помощью конструктора Number

var res = arr.filter(Number); // [1, 2, true, 4, 6, 7, 9, Array[1]]

ожидаются true и [10] в результирующем массиве? Если подставить false для true в arr

var arr = [1,2,false,4,{"abc":123},6,7,{"def":456},9,[10]] 
var res = arr.filter(Number) // [1, 2, 4, 6, 7, 9, Array[1]]

используя Array.isArray

var res = arr.filter(Array.isArray) // [Array[1]]

String

var res = arr.filter(String) // [1, 2, true, 4, Object, 6, 7, Object, 9, Array[1]]

Если мы хотим фильтровать элементы внутри arr, которые являются объектами, в индексах 4, 7 и мы пытаемся выполнить

var res = arr.filter(Object) // [1, 2, true, 4, Object, 6, 7, Object, 9, Array[1]]

Хотя мы бы предпочли просто называть arr.filter(Object), мы могли бы передать вызов функции; пробовать разные свойства Object, чтобы мы могли в конечном итоге найти свойство или метод, которые мы могли бы использовать как функцию или конструктор для передачи в качестве шаблона arr.filter(/* method, constructor, other approach */), чтобы возвращать отфильтрованные результаты, соответствующие объекту, или даже имя или значение свойства объекта внутри входного массива.

Мы начинаем, невинно, проверяя, имеет ли элемент в массиве constructor имеющий name равный "Object"

 var res = arr.filter(function(prop) {
  return prop.constructor.name === "Object"
 }) // [Object, Object]

хотя при добавлении объекта в arr; например;.

 var c = Object.create(null); arr.push(c); 

 var res = arr.filter(function(prop) {
   return prop.constructor.name === "Object"
 }) // `Uncaught TypeError: Cannot read property 'name' of undefined`

как c prototype и constructor являются undefined. Хотя мы уверены, что это не вернет ожидаемых результатов

var n = arr.filter(Object.hasOwnProperty, "abc"); // [1, 2]

по крайней мере ошибка не была возвращена; продолжим

var n = arr.filter(function(prop, val) {
          return prop.hasOwnProperty(this.valueOf())
        }, "abc"); // [Object abc: 123__proto__: Object]

ожидаемые результаты возвращаются; хотя мы пытаемся использовать

var n = arr.filter(/* function reference */, this /* optional parameters passed */)

to

  • фильтровать массив для объектов Object: {}; даже если объект не имеет определенного прототипа или конструктора; возможно преобразование JSON string "{"abc":123}" в объект; хотя мы еще не дошли до этого,

  • передать имя свойства в шаблон .filter(callback, this), где this служит именем свойства или значением объекта; или использовать подход с использованием filter.bind, .call или .apply или другого метода для фильтрации объекта из входного массива - без использования полного

    .filter(function(prop, value) {})

    шаблон. Как мы можем принудить вызов Object.hasOwnProperty() к шаблону, аналогичному

    .filter(Object.hasOwnProperty, "abc")

?

Упоминание .call, .bind и .apply после поиска аналогичного Вопроса и поиска JS Array.prototype.filter на прототипе метода. Хотя и не определено, как реализовать подходы, описанные при фильтрации объектов и объектов, обладающих определенными свойствами, как описано выше.

Примечание. Вопрос также может быть разрешен с помощью destructuring или другого подхода es-6, es-7, обеспечивая сопоставимые или даже более строгие результаты по сравнению с .filter(). То есть, используйте .filter() без

   function(prop, value) {

   }

шаблон. Возвращаемые объекты; то есть Object, {}; и объекты, отфильтрованные по свойству; объекты, отфильтрованные по значению свойства.


Вопросы:

  • Как фильтровать объекты с прототипом или конструктором Object или внутри него в массиве, переданном в Array.prototype.filter() без использования анонимной функции callback pattern?

  • Как фильтровать определенные объекты в массиве, переданные в Array.prototype.filter(), передавая имя или значение свойства для соответствия объекту без использования анонимной функции callback pattern?

4b9b3361

Ответ 1

Как фильтровать объекты с прототипом или конструктором объекта или без него внутри массива, переданного в Array.prototype.filter(), без использования анонимная функция callbackpattern?

По spec

callbackfn должна быть функцией, которая принимает три аргумента и возвращает значение, которое является принудительным для логического значения true или false

Объект Number (конструктор функций) возвращает NaN для плохого Преобразование чисел, но конструкторы String и Object не возвращают ложное значение (да, filter(Number) также отфильтровывает 0)

var arr = [0,1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]];
arr.filter(Number); //outputs [1, 2, true, 4, 6, 7, 9, Array[1]]

Вы можете создать клиентскую функцию OBJ,

function OBJ(value,index,arr){ return typeof value === "object" && !Array.isArray(value) }

или Массивы также приветствуются в наборе результатов, затем удалите проверку Array.isArray

function OBJ(value,index,arr){ return typeof value === "object" }

при использовании с

arr.filter(OBJ); //outputs [{"abc":123},{"def":456}]

Ответ 2

Нет реального способа сделать это безопасно, не создавая свою собственную функцию. Кроме того, это очень сложно, потому что определение Object слишком велико.

Начнем со следующего:

var types = ['1', 2, true, null, undefined, [], {}, new Date()];

и выполните следующее:

types.map((e) => typeof e);
// ["string", "number", "boolean", "object", "undefined", "object", "object", "object"]

Как вы думаете, null как Object? Я так не думаю. Вы думаете о Array как о Object, потому что Array является экземпляром Object? Я тоже не уверен.

Что вы можете попробовать, это следующее:

types.map(Object.isExtensible);
// [false, false, false, false, false, true, true, true]

Это исключает null из результата, но все же массив присутствует здесь. Date Object здесь, а также любой другой Object с любым prototype, например. new Boolean() также будет Object. Кроме того, объект может быть заморожен, и он также не будет возвращен как Object.

Итак, оба примера здесь успешно демонстрируют, что определение Object является слишком широким, и его нельзя реально обработать полезным способом.

Ответ 3

Кажется, вы хотите отфильтровать массив для элементов с определенным типом. Передайте соответствующую функцию filter:

array.filter(istype("String"))

Вам просто нужно написать istype сейчас:

function istype(type) {
  return function(x) {
    return Object.prototype.toString.call(x) === '[object ' + type + ']';
  }
}

Кажется, вы считали, что можете фильтровать номера, говоря filter(Number) и т.д. Но это не сработает. Number - это еще одна функция, которая пытается превратить что-то в число ( not проверить, является ли это числом). Затем filter фильтрует массив в зависимости от того, является ли результат правдивым или ложным. Number будет давать истинное значение для любого ненулевого числа, очевидно, и true. Для строки или объекта или всего остального он возвращает NaN, который является ложным, с нечетными исключениями, такими как возврат 0 для [] или цельная строка.

То же самое со строкой. String - это еще одна функция, которая пытается превратить что-то в строку. Затем filter фильтрует массив в зависимости от того, является ли результат правдивым или ложным. String создаст правдивое значение почти для чего-либо, кроме непустой строки.

Это не имеет ничего общего с деструктурированием; почему вы думаете, что это так? Вы можете удалить эту неудачную часть своего сообщения. Также не ясно, что вы подразумеваете под "вызовом фильтра без обратного вызова" - с помощью обратного вызова для определения того, какие элементы для фильтрации и выхода являются всей ДНК filter. Также неясно, какой шаблон вы имеете в виду, когда вы произносите function(prop, value) { } шаблон.

В конце вашего вопроса вы задаете два конкретных вопроса:

Как фильтровать объекты с или без прототипа или конструктора объекта внутри массива, переданного в Array.prototype.filter() без использования анонимной функции callbackpattern?

Вы фильтруете объекты из входного массива, предоставляя функцию, которая определяет, является ли конкретный элемент объектом. Это не прототип объекта или конструктор Object, так что это вам не поможет. Вам нужно написать небольшую функцию, чтобы перейти к filter, как это работает. Он может быть анонимным, или он может быть определен в другом месте и передан в

Как фильтровать определенные объекты в массиве, переданные в Array.prototype.filter(), передавая имя или значение свойства для соответствия объекту без использования обратного шаблона анонимной функции?

Что вы подразумеваете под "передачей имени или значения свойства для соответствия объекту"? Вы имеете в виду, отфильтровывать элементы, которым не хватает определенного имени или ценности свойства? Затем напишите функцию для этого. Для этой цели нет встроенной функции, если это то, что нужно.

Ответ 4

Без передачи функции обратного вызова вместо этого вы можете передать регулярное выражение с помощью метода RegExp.prototype.test и привязки регулярного выражения

var arr = [1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]]

var res = arr.filter(RegExp.prototype.test.bind(/\[object Object\]/));

console.log(res)

Ответ 5

В ES6 следующее будет отображаться в приведенных ниже примерах:

arr.filter(Object.isExtensible)

Очевидно, что это исключает объекты, которые были помечены как не растяжимые, путем вызова Object.freeze, Object.seal или Object.preventExtensions. Если вы не планируете использовать их, я считаю, что это делает эту работу.

var arr = [
    /* primitives: */
    2, true, "str", null, undefined, NaN, 
    /* objects */
    new Number(2), {a:1}, Object.create(null), [10], x=>x, new Date(), new Set()
];

var objects = arr.filter(Object.isExtensible);

console.log(objects);

Ответ 6

Ближайшие до сих пор смогли достичь требования, также соответствуют Object.create(null)

var res = []; for (let p of arr) /^\{?.+\}$/.test(JSON.stringify(p)) && res.push(p)