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).