Given
var arr = [1,2,true,4,{"abc":123},6,7,{"def":456},9,[10]]
we can filter number items within array arr
using Number
constructor
var res = arr.filter(Number); // [1, 2, true, 4, 6, 7, 9, Array[1]]
are true
and [10]
expected in resulting array ? If we substitute false
for true
at 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]]
using 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]]
If we want to filter items within arr
that are object, at indexes 4
, 7
and we try
var res = arr.filter(Object) // [1, 2, true, 4, Object, 6, 7, Object, 9, Array[1]]
Although we would prefer to simply call arr.filter(Object)
, we could pass a function call; trying different properties of Object
so that we can eventually find a property or method that we could use as a function or constructor to pass to as the pattern arr.filter(/* method, constructor, other approach */)
to return the filtered results matching the object, or even property name or value of the object within the input array.
We start, innocently enough, by checking if the item in the array has a constructor
having name
equal to "Object"
var res = arr.filter(function(prop) {
return prop.constructor.name === "Object"
}) // [Object, Object]
though when we add an object to arr
; e.g.;
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`
as c
prototype
and constructor
are undefined
. Although we are certain that this will not return expected results
var n = arr.filter(Object.hasOwnProperty, "abc"); // [1, 2]
at least an error was not returned; let us continue
var n = arr.filter(function(prop, val) {
return prop.hasOwnProperty(this.valueOf())
}, "abc"); // [Object abc: 123__proto__: Object]
the expected results are returned; though we are trying to use
var n = arr.filter(/* function reference */, this /* optional parameters passed */)
to
filter an array for
Object
:{}
objects; even if the object does not have a defined prototype or constructor; optionally convertingJSON
string"{"abc":123}"
to object; though we have not reached this far, yet;pass a property name to
.filter(callback, this)
pattern wherethis
serves as property name, or value of object; or utilize an approach usingfilter.bind
,.call
or.apply
or other method to filter an object from the input array - without using full.filter(function(prop, value) {})
pattern. How can we coerce the
Object.hasOwnProperty()
call into a pattern similar to.filter(Object.hasOwnProperty, "abc")
?
Mentioning .call
, .bind
and .apply
after searching for a similar Question and finding JS Array.prototype.filter on prototype method . Though not certain how to implement approaches described in filtering both objects and objects having specific properties as described above.
Note, Question can also be resolved by a destructuring
, or other es-6
, es-7
approach, providing comparable or, even stricter results, when compared to .filter()
. That is, use .filter()
without
function(prop, value) {
}
pattern. Returning objects; that is Object
, {}
; and objects filtered by property ; objects filtered by property value.
Questions:
How to filter objects with or without
Object
prototype or constructor within in an array passed toArray.prototype.filter()
without using an anonymous functioncallback
pattern ?How to filter specific objects within an array passed to
Array.prototype.filter()
by passing property name or value to match object without using anonymous functioncallback
pattern ?
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,
function OBJ(value,index,arr){ return typeof value === "object" && !Array.isArray(value) }
or Arrays are also welcome in the resultset then remove the Array.isArray
check
function OBJ(value,index,arr){ return typeof value === "object" }
when used with
arr.filter(OBJ); //outputs [{"abc":123},{"def":456}]
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, [], {}, new Date()];
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.
You seem to want to filter an array for elements with a certain type. Pass an appropriate function to filter
:
array.filter(istype("String"))
You just need to write istype
now:
function istype(type) {
return function(x) {
return Object.prototype.toString.call(x) === '[object ' + type + ']';
}
}
You seem to have thought you could filter for numbers by saying filter(Number)
etc. But that will not work. Number
is just another function, which tries to turn something into a number (not check if it's a number). Then, filter
filters the array depending on whether the result is truthy or falsy. Number
will produce a truthy value for any non-zero number obviously, and true
. For a string, or an object, or pretty much anything else, it will return NaN, which is falsy, with odd exceptions such as returning 0
for []
or an all-blank string.
Same with string. String
is just another function, which tries to turn something into a string. Then, filter
filters the array depending on whether the result is truthy or falsy. String
will produce a truthy value for almost anything other than a non-empty string.
This has nothing whatsoever to do with destructuring; why would you think it does? You might want to remove that unfortunate part of your post. Nor is it clear what you mean by "calling filter without a callback"--using a callback to determine which elements to filter in and out is the entire DNA of filter
. It is also unclear what pattern you are referring to when you say function(prop, value) { }
pattern.
At the end of your question, you ask two specific questions:
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 ?
You filter objects from an input array by providing a function which determines if a particular element is an object. That is not what the object prototype or constructor Object
is, so that won't help you. You have to write a little function to pass to filter
, that's how it works. It could be anonymous, or it could be defined elsewhere and passed in
How to filter specific objects within an array passed to Array.prototype.filter() by passing property name or value to match object without using anonymous function callback pattern ?
What do you mean by "passing property name or value to match object"? Do you mean, filter out elements which are missing a particular property name or value? Then write a function to do that. There is no built-in function for this purpose, if that is what are looking for.
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.
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 */
new Number(2), {a:1}, Object.create(null), [10], x=>x, new Date(), new Set()
];
var objects = arr.filter(Object.isExtensible);
console.log(objects);
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)
来源:https://stackoverflow.com/questions/36232576/how-to-filter-object-using-array-prototype-filter