348

ECMAScript 5 has the filter() prototype for Array types, but not Object types, if I understand correctly.

How would I implement a filter() for Objects in JavaScript?

Let's say I have this object:

var foo = {
    bar: "Yes"
};

And I want to write a filter() that works on Objects:

Object.prototype.filter = function(predicate) {
    var result = {};

    for (key in this) {
        if (this.hasOwnProperty(key) && !predicate(this[key])) {
            result[key] = this[key];
        }
    }

    return result;
};

This works when I use it in the following demo, but when I add it to my site that uses jQuery 1.5 and jQuery UI 1.8.9, I get JavaScript errors in FireBug.

Object.prototype.filter = function(predicate) {
  var result = {};
  for (key in this) {
    if (this.hasOwnProperty(key) && !predicate(this[key])) {
      console.log("copying");
      result[key] = this[key];
    }
  }
  return result;
};

var foo = {
  bar: "Yes",
  moo: undefined
};

foo = foo.filter(function(property) {
  return typeof property === "undefined";
});

document.getElementById('disp').innerHTML = JSON.stringify(foo, undefined, '  ');
console.log(foo);
#disp {
  white-space: pre;
  font-family: monospace
}
<div id="disp"></div>
Alireza
  • 100,211
  • 27
  • 269
  • 172
  • 1
    What errors do you get, specifically? – NT3RP Feb 21 '11 at 22:43
  • What are the errors you're getting? Post them if possible :) – Zack The Human Feb 21 '11 at 22:45
  • There's a bit of ambiguous history wrt jQuery and scripts that extend `Object.prototype`: http://bugs.jquery.com/ticket/2721 – Crescent Fresh Feb 22 '11 at 02:44
  • exactly what I needed, except that you must remove the "!" in the !predicate(this[key]) to have the real filter method. – NoxFly Mar 25 '20 at 14:44
  • Those even mentioning extending the Object prototype, who are not interns, get my recommendation to get immediately fired. There is NO USE CASE where that is a desirable solution. You are basically rewriteing the language with that, since you took the one thing everything in JS is and said: let me make that a little bit different. Yes the language lets you mess with its highest prototype but you should really know better. To make you an analogy - imagine if you took your car and made it a little bit different. Breaks are no longer working if speed is between 59 and 60. – DanteTheSmith Aug 24 '21 at 13:08

19 Answers19

447

First of all, it's considered bad practice to extend Object.prototype. Instead, provide your feature as stand-alone function, or if you really want to extend a global, provide it as utility function on Object, just like there already are Object.keys, Object.assign, Object.is, ...etc.

I provide here several solutions:

  1. Using reduce and Object.keys
  2. As (1), in combination with Object.assign
  3. Using map and spread syntax instead of reduce
  4. Using Object.entries and Object.fromEntries

1. Using reduce and Object.keys

With reduce and Object.keys to implement the desired filter (using ES6 arrow syntax):

Object.filter = (obj, predicate) => 
    Object.keys(obj)
          .filter( key => predicate(obj[key]) )
          .reduce( (res, key) => (res[key] = obj[key], res), {} );

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1); 
console.log(filtered);

Note that in the above code predicate must be an inclusion condition (contrary to the exclusion condition the OP used), so that it is in line with how Array.prototype.filter works.

2. As (1), in combination with Object.assign

In the above solution the comma operator is used in the reduce part to return the mutated res object. This could of course be written as two statements instead of one expression, but the latter is more concise. To do it without the comma operator, you could use Object.assign instead, which does return the mutated object:

Object.filter = (obj, predicate) => 
    Object.keys(obj)
          .filter( key => predicate(obj[key]) )
          .reduce( (res, key) => Object.assign(res, { [key]: obj[key] }), {} );

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1); 
console.log(filtered);

3. Using map and spread syntax instead of reduce

Here we move the Object.assign call out of the loop, so it is only made once, and pass it the individual keys as separate arguments (using the spread syntax):

Object.filter = (obj, predicate) => 
    Object.assign(...Object.keys(obj)
                    .filter( key => predicate(obj[key]) )
                    .map( key => ({ [key]: obj[key] }) ) );

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};
var filtered = Object.filter(scores, score => score > 1); 
console.log(filtered);

4. Using Object.entries and Object.fromEntries

As the solution translates the object to an intermediate array and then converts that back to a plain object, it would be useful to make use of Object.entries (ES2017) and the opposite (i.e. create an object from an array of key/value pairs) with Object.fromEntries (ES2019).

It leads to this "one-liner" method on Object:

Object.filter = (obj, predicate) => 
                  Object.fromEntries(Object.entries(obj).filter(predicate));

// Example use:
var scores = {
    John: 2, Sarah: 3, Janet: 1
};

var filtered = Object.filter(scores, ([name, score]) => score > 1); 
console.log(filtered);

The predicate function gets a key/value pair as argument here, which is a bit different, but allows for more possibilities in the predicate function's logic.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • Could it be more complex query? For example: `x => x.Expression.Filters.Filter` – hackp0int Oct 19 '16 at 11:16
  • 2
    @IamStalker, did you try? It does not matter, as long as you provide a valid function in the second argument. NB: I have no idea what `.Filter` is at the end, but if it is a function, you need to call it ( `x => x.Expression.Filters.Filter()` ) – trincot Oct 19 '16 at 12:36
  • so long! can be done on 1 line . [check this](http://stackoverflow.com/a/40562289/747579) – Abdennour TOUMI Nov 12 '16 at 11:17
  • 1
    Newer features may make for less code, but they also make for [*slower performance*](https://jsperf.com/ed-3-vs-es-2015-vs-es-2016/1). Ed 3 compliant code runs more than twice as fast in most browsers. – RobG Feb 24 '17 at 23:17
  • 3
    TypeScript version of the last variant: https://gist.github.com/OliverJAsh/acafba4f099f6e677dbb0a38c60dc33d – Oliver Joseph Ash Jan 03 '19 at 15:14
  • To more closely mimic the Array.filter method, I would suggest using the following arguments when calling the predicate (value, propertyName, object) `predicate(obj[key], key, obj)` – Ben White Jun 28 '19 at 18:30
  • This can be a question in itself. Which of these should I use to get a value in an object :) – FabricioG Feb 06 '20 at 22:18
  • 1
    @Fabricio, to get a "value in an object", you just do `object[key] = value`. Yes, if you are stuck on a coding problem, then please ask a new question. If you want to have info about efficiency, good coding style, for *working* code, then check out [CodeReview](https://codereview.stackexchange.com/) – trincot Feb 07 '20 at 08:25
  • 2
    I have no doubts this is the best solution of all. Congratulations. My favorite solution is the combination with `entries` and `fromEntries`. So simple, yet so readable, comprehensible, powerful and a higher-level abstraction! – Victor Nov 29 '20 at 19:59
  • Solution 3 fails for me if there are null values in the object, not exactly sure how I should deal with that – Ciaran Gallagher Jun 03 '21 at 11:17
  • 1
    @CiaranGallagher, when I add `other: null` as extra property in the sample object, then snippet #3 still runs fine. I suppose your filter condition is checking a property of each value, which only makes sense if your values are not `null`. You can use the `??` operator in your filter condition if that is your case. But this has little to do with the answer here, but more with providing a solid filter condition. – trincot Jun 03 '21 at 13:27
  • How would one put solution #1 into a utility file and export/import it? – lowcrawler Oct 01 '21 at 04:47
  • 1
    @lowcrawler, there is nothing to export, as this mutates the global `Object` variable. There is no `export` needed, and you can just do `import 'myfile'` without assignment. – trincot Oct 01 '21 at 06:15
  • As @RobG hinted: how would these different approaches compare performance-wise? – Cadoiz Mar 27 '23 at 07:00
291

Never ever extend Object.prototype.

Horrible things will happen to your code. Things will break. You're extending all object types, including object literals.

Here's a quick example you can try:

    // Extend Object.prototype
Object.prototype.extended = "I'm everywhere!";

    // See the result
alert( {}.extended );          // "I'm everywhere!"
alert( [].extended );          // "I'm everywhere!"
alert( new Date().extended );  // "I'm everywhere!"
alert( 3..extended );          // "I'm everywhere!"
alert( true.extended );        // "I'm everywhere!"
alert( "here?".extended );     // "I'm everywhere!"

Instead create a function that you pass the object.

Object.filter = function( obj, predicate) {
    let result = {}, key;

    for (key in obj) {
        if (obj.hasOwnProperty(key) && !predicate(obj[key])) {
            result[key] = obj[key];
        }
    }

    return result;
};
Mikey
  • 2,675
  • 4
  • 18
  • 24
user113716
  • 318,772
  • 63
  • 451
  • 440
  • @patrick: you might wish to give a reason, so it is slightly more informative :P – Martin Jespersen Feb 21 '11 at 22:45
  • @Martin: I'm hoping to appeal to OP's fear of the unknown. ;o) – user113716 Feb 21 '11 at 22:47
  • 118
    @patrick: give a man a bread and you'll feed him for a day, teach him how to bake and you'll feed him for a lifetime (or something, I'm danish, I don't know the correct English sayings ;) – Martin Jespersen Feb 21 '11 at 22:52
  • @Dykam: Yeah, I originally saw the question as *why is this breaking my code*. Updated with a solution. – user113716 Feb 21 '11 at 22:53
  • @Martin: Make him afraid of heights, and he'll never die in a plane crash. ;o) – user113716 Feb 21 '11 at 22:54
  • @patrick, don't forget to declare the `key` variable in the `for-in` loop ;) – Christian C. Salvadó Feb 21 '11 at 23:15
  • @CMS: Ugh, you caught me on that again! I'm not sure how many more times I'll be able to use the copy/paste defense. :o) EDIT: Fixed. And thanks. :o) – user113716 Feb 21 '11 at 23:19
  • 22
    You're doing it wrong... !predicate(obj[key]) should be predicate(obj[key]) – pyrotechnick Aug 22 '11 at 06:15
  • 13
    @pyrotechnick: No. First, the main point of the answer is to not extend `Object.prototype`, but rather to just place the function on `Object`. Second, *this is the OP's code*. Clearly OP's intention is to have `.filter()` be such that it *filters out* the positive results. In other words, it is a negative filter, where a positive return value means it is *excluded* from the result. If you look at the jsFiddle example, he's filtering out existing properties that are `undefined`. – user113716 Aug 22 '11 at 13:09
  • 6
    @patrick dw: No. First, I didn't mention extending/not extending prototypes. Second, https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/filter -- "Creates a new array with all elements that pass the test implemented by the provided function." Implementing the exact opposite on a global seems pretty silly, doesn't it? – pyrotechnick Aug 30 '11 at 06:58
  • 11
    @pyrotechnick: That's right, you didn't mention extending/not extending prototypes, and that's my point. You said I'm doing it wrong, but the only "it" I'm doing is telling OP to not extend `Object.prototype`. From the question: **"This works..., but when I add it to my site..., I get JavaScript errors"** If OP decides to implement a `.filter()` with the opposite behavior of that of `Array.prototpe.filter`, that's up to him/her. Please leave a comment under the question if you want to notify OP that the code is wrong, but don't tell me that *I'm* doing it wrong when it isn't my code. – user113716 Aug 30 '11 at 12:42
  • 1
    What's the point of having to call this with Object.filter(...)? Is that some kind of coding convention? It doesn't need to be a function on Object. – kristianp Nov 17 '17 at 04:56
  • Can someone please explain the pattern ```for (key in obj){if obj.hasOwnProperty(key){....}}``` AFAIK, every key in this for loop is an enumerable property of obj, and hence obj.hasOwnProperty will always return true. What am I missing? In which cases will it return false? – Ben Carp Jun 03 '18 at 15:34
  • 3
    @BenCarp objects come with other properties not defined by the user, built-in ones so its just to avoid those – Emobe Mar 20 '19 at 09:17
  • @MartinJespersen i don't think the saying needs further translation, it is very accurate the way it is. –  Sep 10 '19 at 13:46
  • @MartinJespersen It's "give a man a fish; feed him for a day. Teach a man to fish; feed him for a lifetime". My favorite variation: "Give a man a fire; he'll be warm for a day; Set a man on fire; he'll be warm for the rest of his lifetime" – Justin May 21 '20 at 08:09
  • +1 for answering the question while also explaining why not to. Someone *might* want to extend objects (a test suite that checks for people doing bad things?), which I did. So many SO answers tell you not to do something while forgetting to tell you how to do it. – Erik Aronesty Jul 04 '20 at 07:18
  • @user113716, I believe pyrotechnick is right, in a sense. Sure, you answered OP's question, but as it turns out, this is the top answer to a SO question with 424k views. The fact is, most people are going to come here looking for a Object.filter function, not what you have written. I came back to write this comment because the filter function I copied from your answer wasn't working and I imagine that isn't the first time that has happened. Regardless, thank you for writing such a well thought out response to OPs question. – SamB Dec 16 '20 at 21:28
157

Solution in Vanilla JS from year 2020.


let romNumbers={'I':1,'V':5,'X':10,'L':50,'C':100,'D':500,'M':1000}

You can filter romNumbers object by key:

const filteredByKey = Object.fromEntries(
    Object.entries(romNumbers).filter(([key, value]) => key === 'I') )
// filteredByKey = {I: 1} 

Or filter romNumbers object by value:

 const filteredByValue = Object.fromEntries(
    Object.entries(romNumbers).filter(([key, value]) => value === 5) )
 // filteredByValue = {V: 5} 
aljgom
  • 7,879
  • 3
  • 33
  • 28
Qui-Gon Jinn
  • 3,722
  • 3
  • 25
  • 32
  • 3
    Awesome solution! Breaking an Object into `entries`, filtering by desired conditions, then create a new Object with `fromEntries`. – Victor Nov 25 '20 at 21:37
  • 3
    I used that solution to filter the object by multiple keys via `includes`. `Object.fromEntries(Object.entries(romNumbers).filter(([key, value]) => ['a', 'b', 'c', 'd', 'e'].includes(key)))` – Victor Nov 25 '20 at 21:39
  • 2
    Not sure why you repeat an answer that was given more than a [year earlier](https://stackoverflow.com/a/37616104/5459839) – trincot Nov 29 '20 at 20:18
  • For anyone using multidimensional objects, change '=> value === 5' to '=> value.secondaryValue === 5' – Rasmus Jan 13 '22 at 09:10
30

If you're willing to use underscore or lodash, you can use pick (or its opposite, omit).

Examples from underscore's docs:

_.pick({name: 'moe', age: 50, userid: 'moe1'}, 'name', 'age');
// {name: 'moe', age: 50}

Or with a callback (for lodash, use pickBy):

_.pick({name: 'moe', age: 50, userid: 'moe1'}, function(value, key, object) {
  return _.isNumber(value);
});
// {age: 50}
Bogdan D
  • 5,321
  • 2
  • 31
  • 32
25

ES6 approach...

Imagine you have this object below:

const developers = {
  1: {
   id: 1,
   name: "Brendan", 
   family: "Eich"
  },
  2: {
   id: 2,
   name: "John", 
   family: "Resig"
  },  
  3: {
   id: 3,
   name: "Alireza", 
   family: "Dezfoolian"
 }
};

Create a function:

const filterObject = (obj, filter, filterValue) => 
   Object.keys(obj).reduce((acc, val) => 
   (obj[val][filter] === filterValue ? acc : {
       ...acc,
       [val]: obj[val]
   }                                        
), {});

And call it:

filterObject(developers, "name", "Alireza");

and will return:

{
  1: {
  id: 1,
  name: "Brendan", 
  family: "Eich"
  },
  2: {
   id: 2,
   name: "John", 
   family: "Resig"
  }
}
Alireza
  • 100,211
  • 27
  • 269
  • 172
  • 1
    Looks good! But why does it return just the other object (and not the one with the name/filterValue of "Alireza")? – Pille Feb 07 '19 at 16:19
  • 1
    @Pille, the OP asked for it to be like that (note the negative filter with `!predicate` in their own code). – trincot Mar 19 '19 at 18:50
9

Given

object = {firstname: 'abd', lastname:'tm', age:16, school:'insat'};

keys = ['firstname', 'age'];

then :

keys.reduce((result, key) => ({ ...result, [key]: object[key] }), {});
// {firstname:'abd', age: 16}

// Helper
function filter(object, ...keys) {
  return keys.reduce((result, key) => ({ ...result, [key]: object[key] }), {});
  
};

//Example
const person = {firstname: 'abd', lastname:'tm', age:16, school:'insat'};

// Expected to pick only firstname and age keys
console.log(
  filter(person, 'firstname', 'age')
)
Abdennour TOUMI
  • 87,526
  • 38
  • 249
  • 254
9

As patrick already stated this is a bad idea, as it will almost certainly break any 3rd party code you could ever wish to use.

All libraries like jquery or prototype will break if you extend Object.prototype, the reason being that lazy iteration over objects (without hasOwnProperty checks) will break since the functions you add will be part of the iteration.

Martin Jespersen
  • 25,743
  • 8
  • 56
  • 68
6

Plain ES6:

var foo = {
    bar: "Yes"
};

const res = Object.keys(foo).filter(i => foo[i] === 'Yes')

console.log(res)
// ["bar"]
francis
  • 3,852
  • 1
  • 28
  • 30
5

How about:

function filterObj(keys, obj) {
  const newObj = {};
  for (let key in obj) {
    if (keys.includes(key)) {
      newObj[key] = obj[key];
    }
  }
  return newObj;
}

Or...

function filterObj(keys, obj) {
  const newObj = {};
  Object.keys(obj).forEach(key => {
    if (keys.includes(key)) {
      newObj[key] = obj[key];
    }
  });
  return newObj;
}
shaunw
  • 360
  • 1
  • 3
  • 10
5
    var foo = {
    bar: "Yes",
    pipe: "No"
};

const ret =  Object.entries(foo).filter(([key, value])=> value === 'Yes');

https://masteringjs.io/tutorials/fundamentals/filter-object

4

I have created an Object.filter() which does not only filter by a function, but also accepts an array of keys to include. The optional third parameter will allow you to invert the filter.

Given:

var foo = {
    x: 1,
    y: 0,
    z: -1,
    a: 'Hello',
    b: 'World'
}

Array:

Object.filter(foo, ['z', 'a', 'b'], true);

Function:

Object.filter(foo, function (key, value) {
    return Ext.isString(value);
});

Code

Disclaimer: I chose to use Ext JS core for brevity. Did not feel it was necessary to write type checkers for object types as it was not part of the question.

// Helper function
function print(obj) {
    document.getElementById('disp').innerHTML += JSON.stringify(obj, undefined, '  ') + '<br />';
    console.log(obj);
}

Object.filter = function (obj, ignore, invert) {
    let result = {}; // Returns a filtered copy of the original list
    if (ignore === undefined) {
        return obj;   
    }
    invert = invert || false;
    let not = function(condition, yes) { return yes ? !condition : condition; };
    let isArray = Ext.isArray(ignore);
    for (var key in obj) {
        if (obj.hasOwnProperty(key) &&
                !(isArray && not(!Ext.Array.contains(ignore, key), invert)) &&
                !(!isArray && not(!ignore.call(undefined, key, obj[key]), invert))) {
            result[key] = obj[key];
        }
    }
    return result;
};

let foo = {
    x: 1,
    y: 0,
    z: -1,
    a: 'Hello',
    b: 'World'
};

print(Object.filter(foo, ['z', 'a', 'b'], true));
print(Object.filter(foo, (key, value) => Ext.isString(value)));
#disp {
    white-space: pre;
    font-family: monospace
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/extjs/4.2.1/builds/ext-core.min.js"></script>
<div id="disp"></div>
Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • Please check my vanilla [answer](https://stackoverflow.com/a/53767983/3645375) and [gist](https://gist.github.com/khullah/872d5a174108823159d845cc5baba337) – Bernardo Dal Corno Dec 13 '18 at 18:24
4

My opinionated solution:

function objFilter(obj, filter, nonstrict){
  r = {}
  if (!filter) return {}
  if (typeof filter == 'string') return {[filter]: obj[filter]}
  for (p in obj) {
    if (typeof filter == 'object' &&  nonstrict && obj[p] ==  filter[p]) r[p] = obj[p]
    else if (typeof filter == 'object' && !nonstrict && obj[p] === filter[p]) r[p] = obj[p]
    else if (typeof filter == 'function'){ if (filter(obj[p],p,obj)) r[p] = obj[p]}
    else if (filter.length && filter.includes(p)) r[p] = obj[p]
  }
  return r
}

Test cases:

obj = {a:1, b:2, c:3}

objFilter(obj, 'a') // returns: {a: 1}
objFilter(obj, ['a','b']) // returns: {a: 1, b: 2}
objFilter(obj, {a:1}) // returns: {a: 1}
objFilter(obj, {'a':'1'}, true) // returns: {a: 1}
objFilter(obj, (v,k,o) => v%2===1) // returns: {a: 1, c: 3}

https://gist.github.com/bernardoadc/872d5a174108823159d845cc5baba337

Bernardo Dal Corno
  • 1,858
  • 1
  • 22
  • 27
3

If you have Symbol properties in your object, that should be filtered too, you can not use: Object.keys Object.entries Object.fromEntries, ... because:

Symbol keys are not enumerable !

You could use Reflect.ownKeys and filter keys in reduce

Reflect.ownKeys(o).reduce((a, k) => allow.includes(k) && {...a, [k]: o[k]} || a, {});

(Open DevTools for log output - Symbols are not logged on Stackoverflow UI)

const bKey = Symbol('b_k');
const o = {
    a:                 1,
    [bKey]:            'b',
    c:                 [1, 3],
    [Symbol.for('d')]: 'd'
};

const allow = ['a', bKey, Symbol.for('d')];

const z1 = Reflect.ownKeys(o).reduce((a, k) => allow.includes(k) && {...a, [k]: o[k]} || a, {});

console.log(z1);                   // {a: 1, Symbol(b_k): "b", Symbol(d): "d"}
console.log(bKey in z1)            // true
console.log(Symbol.for('d') in z1) // true

This is equal to this

const z2 = Reflect.ownKeys(o).reduce((a, k) => allow.includes(k) && Object.assign(a, {[k]: o[k]}) || a, {});
const z3 = Reflect.ownKeys(o).reduce((a, k) => allow.includes(k) && Object.defineProperty(a, k, {value: o[k]}) || a, {});

console.log(z2); // {a: 1, Symbol(b_k): "b", Symbol(d): "d"}
console.log(z3); // {a: 1, Symbol(b_k): "b", Symbol(d): "d"}

Wrapped in a filter() function, an optional target object could be passed

const filter = (o, allow, t = {}) => Reflect.ownKeys(o).reduce(
    (a, k) => allow.includes(k) && {...a, [k]: o[k]} || a, 
    t
);

console.log(filter(o, allow));           // {a: 1, Symbol(b_k): "b", Symbol(d): "d"}
console.log(filter(o, allow, {e: 'e'})); // {a: 1, e: "e", Symbol(b_k): "b", Symbol(d): "d"}
Exodus 4D
  • 2,207
  • 2
  • 16
  • 19
2

You could also do something like this where you are filtering on the entries to find the key provided and return the value

   let func = function(items){
      let val
      Object.entries(this.items).map(k => {
        if(k[0]===kind){
         val = k[1]
        }
      })
      return val
   }
Troy B.
  • 19
  • 3
1

If you wish to mutate the same object rather than create a new one.

The following example will delete all 0 or empty values:

const sev = { a: 1, b: 0, c: 3 };
const deleteKeysBy = (obj, predicate) =>
  Object.keys(obj)
    .forEach( (key) => {
      if (predicate(obj[key])) {
        delete(obj[key]);
      }
    });

deleteKeysBy(sev, val => !val);
yairniz
  • 408
  • 5
  • 7
1

I just wanted to add the way that I do it because it saves me creating extra functions, I think is cleaner and I didn't see this answer:

let object = {a: 1, b: 2, c: 3};
[object].map(({a,c}) => ({a,c}))[0]; // {a:1, c:2}

The cool thing is that also works on arrays of objects:

let object2 = {a: 4, b: 5, c: 6, d: 7};
[object, object2].map(({a,b,c,d}) => ({a,c})); //[{"a":1,"c":3},{"a":4,"c":6}]
[object, object2].map(({a,d}) => ({a,d})); //[{"a":1,"d":undefined},{"a":4,"d":7}]
0

Like everyone said, do not screw around with prototype. Instead, simply write a function to do so. Here is my version with lodash:

import each from 'lodash/each';
import get from 'lodash/get';

const myFilteredResults = results => {
  const filteredResults = [];

  each(results, obj => {
    // filter by whatever logic you want.

    // sample example
    const someBoolean = get(obj, 'some_boolean', '');

    if (someBoolean) {
      filteredResults.push(obj);
    }
  });

  return filteredResults;
};
saran3h
  • 12,353
  • 4
  • 42
  • 54
0

If you don't need the original object, this is a simple, very boring answer that doesn't waste memory:

const obj = {'a': 'want this', 'b': 'want this too', 'x': 'remove this'}
const keep = new Set(['a', 'b', 'c'])

function filterObject(obj, keep) {
  Object.keys(obj).forEach(key => {
    if (!keep.has(key)) {
      delete obj[key]
    }
  })
}

If you're only filtering a small number of objects, and your objects don't have many keys, you might not want to bother with constructing a Set, in which case use array.includes instead of set.has.

Chris
  • 5,664
  • 6
  • 44
  • 55
-2

In these cases I use the jquery $.map, which can handle objects. As mentioned on other answers, it's not a good practice to change native prototypes (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Inheritance_and_the_prototype_chain#Bad_practice_Extension_of_native_prototypes)

Below is an example of filtering just by checking some property of your object. It returns the own object if your condition is true or returns undefined if not. The undefined property will make that record disappear from your object list;

$.map(yourObject, (el, index)=>{
    return el.yourProperty ? el : undefined;
});
Marcel Kohls
  • 1,650
  • 16
  • 24
  • 2
    `$.map` can take an object, but it returns an array, so the original property names are lost. The OP needs a filtered plain object. – trincot Mar 19 '19 at 18:47