To filter entries which aren't strictly arrays, and thus don't have the .filter
property on their prototype, but are still iterable (like document.getElementsByTagName
), you can use
Array.prototype.filter.call(collection, function filterFunction(el, index, collection) {
...
});
Or the shorthand
[].filter.call(collection, function filterFunction(el, index, collection) {
...
});
As for objects which are not iterable, but you still want to filter properties and get an array of keys that pass filtering, you can combine with Object.keys
like so:
var obj = { one: 1, two: 2, three: 3, four: 4 };
var filtered = Object.keys(obj).filter(function(key) {
return obj[key] % 2 === 0;
}); //filtered == ['two', 'four']
Then, you can create a new object containing those properties:
var filteredObj = filtered.reduce(function(newObj, currentKey) {
newObj[currentKey] = obj[currentKey]; //Add the original value to the new object
return newObj; //Return the new object to continue iteration
}, {}) // Begin iteration with a blank object
//filteredObj is now { two: 2, four: 4 }
The above can even be combined into a function!
function filterObject(obj, testCallback) {
return Object.keys(obj).filter(function(key, index, array) {
return testCallback(obj[key], index, array); //Call original filter but pass the property
}).reduce(function(newObj, currentKey) {
newObj[currentKey] = obj[currentKey]; //Add the original value to the new object
return newObj; //Return the new object to continue iteration
}, {}); // Begin iteration with a blank object
}
And use like this:
var obj = { one: 1, two: 2, three: 3, four: 4 };
var filteredObj = filterObject(obj, function(el) { return el % 2 === 0 });