How To Filter Object Using Array.prototype.filter?
Solution 1:
How to filter objects with or without Object prototype or constructor within in an array passed to Array.prototype.filter() without using an anonymous function callbackpattern ?
As per spec
callbackfn should be a function that accepts three arguments and returns a value that is coercible to the Boolean value true or false
Number object (function's constructor) does return NaN for bad Number conversion but String and Object constructors don't return a false value (yes, filter(Number)
also filters out 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]]
You can create a customer function OBJ,
functionOBJ(value,index,arr){ returntypeof value === "object" && !Array.isArray(value) }
or Arrays are also welcome in the resultset then remove the Array.isArray
check
functionOBJ(value,index,arr){ returntypeof value === "object" }
when used with
arr.filter(OBJ); //outputs [{"abc":123},{"def":456}]
Solution 2:
There is no real way to do it safely without creating your own function. Additionally it is very complicated because the definition of Object
is too broad.
Let's start with the following:
var types = ['1', 2, true, null, undefined, [], {}, newDate()];
and run the following:
types.map((e) => typeof e);
// ["string", "number", "boolean", "object", "undefined", "object", "object", "object"]
Do you think of null
of as an Object
? I don't think so. Do you think of an Array
as of an Object
, because the Array
is an instance of Object
? I am not sure as well.
What you can try is the following:
types.map(Object.isExtensible);
// [false, false, false, false, false, true, true, true]
This excludes the null
from the result but still the array is present here. The Date
Object
is here as well as any other Object
with any prototype
, e.g. new Boolean()
will also be an Object
. Additionally the object could be frozen and this won't be returned as an Object
here as well.
So the both examples here successfully demonstrate that the definition of Object
is too broad and it cannot be really handled in a useful way.
Solution 3:
Without passing a callback function, you can instead pass in a regex by using the RegExp.prototype.test
method and binding a regex
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)
This would match any string containing [object Object]
as well, but it seems highly unlikely that a string would contain those exact words, unless you have made a mistake and included stringified objects in your array.
Solution 4:
In ES6 the following would do it for the example values you have listed:
arr.filter(Object.isExtensible)
Obviously, this will exclude objects that have been marked non-extensible, by a call to Object.freeze
, Object.seal
, or Object.preventExtensions
. Unless you plan to use those, I believe this does the job.
var arr = [
/* primitives: */2, true, "str", null, undefined, NaN,
/* objects */newNumber(2), {a:1}, Object.create(null), [10], x=>x, newDate(), newSet()
];
var objects = arr.filter(Object.isExtensible);
console.log(objects);
Solution 5:
The closest have been able to reach to requirement so far, also matches Object.create(null)
var res = []; for (let p of arr) /^\{?.+\}$/.test(JSON.stringify(p)) && res.push(p)
Post a Comment for "How To Filter Object Using Array.prototype.filter?"