I use a lot of lambda expressions in C#, so I've decided to create some similar functionality in JavaScript. Since jQuery is included in my projects, I'm using $.grep()
instead of Array.prototype.filter()
to support older browsers without including shims.
The two examples below corresponds to Where() and FirstOrDefault() in C#:
if(!Array.prototype.where){ Array.prototype.where = function (func) { var that = this; switch (typeof func) { case 'function': return $.grep(that, func); case 'object': for(var prop in func){ that = $.grep(that, function(item){ return item[prop] === func[prop]; }); } return that; default: throw new ReferenceError("no/wrong func type passed"); } }; } if(!Array.prototype.firstOrDefault){ Array.prototype.firstOrDefault = function(func){ return this.where(func)[0] || null; }; }
var persons = [{ name: 'foo', age: 1 }, { name: 'bar', age: 2 }]; var where1 = persons.where(function(p){ return p.age === 1 && p.name === 'foo'; }); console.log(where1); var where2 = persons.where({ age: 1, name: 'foo' }); console.log(where2); var fod1 = persons.firstOrDefault(function(p){ return p.age === 1 && p.name === 'foo'; }); console.log(fod1); var fod2 = persons.firstOrDefault({ age: 1, name: 'foo' }); console.log(fod2);
I would have preferred to add the methods as non-enumerable using Object.defineProperty
, but since I need to support IE >= 7, that's not an option.
However, the only downside with having the methods enumerable would be if someone is iterating an array using for..in
, which they shouldn't do in the fist place.
In case of an object
being passed as argument, one way to decrease the total iterations from array length * object property count to array length * 1 could be solved using the function constructor:
var o = { foo: 1, bar: true, s: 's' }; var str = Object.keys(o).reduce(function (prev, key) { if(typeof o[key] === 'string') o[key] = '\'' + o[key] + '\''; return (prev ? prev + ' && ' : '') + 'x.' + key + ' === ' + o[key]; }, ''); var f = new Function('x', 'return ' + str + ';'); // pass f to filter/$.grep console.log(f);
I would like some feedback about possible performance improvements and what you think about the code in general (but not pros and cons with extending native objects).