lambda.js的由来
作为一个当耐特程序员,对lambda一定不陌生。随着当耐特版本的更新迭代,C#也由委托==〉匿名委托==〉lambda表达式。由于javascript语言的约束,没有提供相应的lambda的机制,所以就有了lambda.js,让广大jser也可以 (a,b)=>a.xx==”yyy”&&b>11 一把!
Query Operator
而lambda最常用的地方就是Query Operator。
比如下面一些C# code:
int[] numbers = { 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 };
int oddNumbers = numbers.Count(n => n % 2 == 1);
对应的javascript code(不使用lambda.js)
var numbers = [ 5, 4, 1, 3, 9, 8, 6, 7, 2, 0 ];
var oddNumbers = _(numbers).count(function (item) { return item % 2 === 1 });
使用lambda.js之后
var numbers = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0];
var oddNumbers = _(numbers).count(_("a=>a%2===1"));
仅此而已?
lambda.js当然提供了underscore.js和JSLINQ都包含的功能!当然lambda.js编程风格更接近jquery style(连缀,大部分方法返回lambda对象)。
var numbers = [5, 4, 1, 3, 9, 8, 6, 7, 2, 0];
var oddNumbers = _(numbers).count(_("a=>a%2===1"));
console.log(oddNumbers===5)
//数组
_(["aa", "bb", "cc"]).each(function (index, item) {
if (index === 0) console.log("arrry each:"+("aa" === item));
if (index === 1) console.log("arrry each:" +( "bb" === item));
if (index === 2) console.log("arrry each:" +( "cc" === item));
})
//支持对象
_({ x: 100, y: 200, name: "zhanglei" }).each(function (key, value) {
if (key == "x") console.log("obj each:" +( value === 100));
if (key == "y") console.log("obj each:"+(value === 200));
if (key == "name") console.log("obj each:"+(value === "zhanglei"));
})
支持map
var aa = _([1, 2, 3]).map(function (item) {
return item * 3;
}).items
console.log("map:"+(aa[0] === 3))
console.log("map:"+(aa[1] === 6))
console.log("map:"+(aa[2] === 9))
//支持对象的数组
var stooges1 = [{ name: 'zhanglei', age: 17 }, { name: 'curly', age: 25 }, { name: 'moe', age: 21 }, { name: 'larry', age: 23 }];
var youngest = _(stooges1).map(function (item) { return item.name + ' is ' + item.age; }).items
console.log(youngest)
//支持查找
var even = _([7, 2, 3, 4, 5, 6, 7, 8, 9]).find(function (item) { return item % 2 == 0; }).items;
console.log(even)
这些都不是关键,关键是可以lambda化,比如这个查询:
var stooges3 = [{ name: 'zhanglei', age: 17 }, { name: 'curly', age: 25 }, { name: 'moe', age: 21 }, { name: 'larry', age: 23 }];
var over18 = _(stooges3)
.find(function (item, index) { return item.age >= 18 && index>0})
.sortBy(function (item) { return item.age })
.first(function (item) { return item.age > 21 })
.map(function (stooge) { return stooge.name + ' is ' + stooge.age; })
.items
;
console.log(over18);
lambda化之后:
var stooges3 = [{ name: 'zhanglei', age: 17 }, { name: 'curly', age: 25 }, { name: 'moe', age: 21 }, { name: 'larry', age: 23 }];
var over18 = _(stooges3)
.find(_("(a,b)=> a.age >= 18 && b > 0 "))
.sortBy(_("b=>b.age"))
.first(_("item=>item.age>21"))
.map(_("i=>i.name + ' is ' + i.age;"))
.items
;
console.log(over18);
lambda.js预览
(function (window) {
var lambda = function (items) {
if (lambda.type(items) === "string") return lambda._compile(items);
return new lambda.prototype.init(items);
},
_lambda = window.lambda,
__ = window._;
lambda.prototype.init = function (items) {
this.items = items;
return this;
}
lambda.prototype.each = function (fn) {
var name, i = 0, length = this.items.length, isObj = length === undefined || lambda.type(this.items) === "function";
var its = this.items;
if (isObj) {
for (name in its) {
fn.call(its[name], name, its[name]);
}
} else {
for (; i < its.length;) {
fn.call(its[i], i, its[i++]);
}
}
}
lambda.prototype.count= function(fn) {
if (fn == null)
return this.items.length;
else
return this.find(fn).items.length;
}
lambda.prototype.map = function (fn) {
var result = [];
this.each(function (index,item) {
result[index]=fn(item);
})
return lambda(result);
}
lambda.prototype.first = function (fn) {
if (fn != null) {
return this.find(fn).first();
}
else {
// If no clause was specified, then return the First element in the Array
if (this.items.length > 0)
return lambda([this.items[0]]);
else
return null;
}
}
lambda.prototype.find = function (fn) {
var newArr=[], self = this, i = 0;
this.each(function (index, item) {
if (fn(item,index)) newArr[i++] = item;
})
return lambda(newArr);
}
lambda.prototype.sortBy = function (clause) {
var tempArray = [];
for (var i = 0; i < this.items.length; i++) {
tempArray[tempArray.length] = this.items[i];
}
return lambda(
tempArray.sort(function (a, b) {
var x = clause(a);
var y = clause(b);
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
})
);
}
lambda.type = function (obj) {
return obj == null ?
String(obj) :
{
"[object Array]": "array",
"[object Boolean]": "boolean",
"[object Date]": "date",
"[object Function]": "function",
"[object Number]": "number",
"[object Object]": "object",
"[object RegExp]": "regexp",
"[object String]": "string"
}[Object.prototype.toString.call(obj)] || "object";
}
lambda._compile = function (condition) {
var conditionStr = condition.split("=>");
if (conditionStr[0].indexOf("(") === -1) {
return function (item) {
return eval(conditionStr[1].replace(new RegExp("\\b" + conditionStr[0] + "(?![A-Za-z0-9_])", "g"), "item"));
}
} else {
var tempStr = conditionStr[0].replace(/\(/g, "").replace(/\)/g, "").split(",");
var tempItem = lambda.trim(tempStr[0]);
var tempIndex = lambda.trim(tempStr[1]);
return function (item,index) {
return eval(conditionStr[1].replace(new RegExp("\\b" + tempItem + "(?![A-Za-z0-9_])", "g"), "item").replace(new RegExp("\\b" + tempIndex + "(?![A-Za-z0-9_])", "g"), "index"));
}
}
}
var trimLeft = /^\s+/,
trimRight = /\s+$/,
rnotwhite = /\S/,
trim = String.prototype.trim;
// IE doesn't match non-breaking spaces with \s
if (rnotwhite.test("\xA0")) {
trimLeft = /^[\s\xA0]+/;
trimRight = /[\s\xA0]+$/;
}
lambda.trim = trim ?
function (text) {
return text == null ?
"" :
trim.call(text);
} :
// Otherwise use our own trimming functionality
function (text) {
return text == null ?
"" :
text.toString().replace(trimLeft, "").replace(trimRight, "");
};
lambda.prototype.init.prototype = lambda.prototype;
lambda.noConflict = function (deep) {
if (window._ === lambda) {
window._ = __;
}
if (deep && window.lambda === lambda) {
window.lambda = _lambda;
}
return lambda;
}
var root = this;
if (typeof exports !== 'undefined') {
if (typeof module !== 'undefined' && module.exports) {
exports = module.exports = lambda = _;
}
exports.lambda = exports._ = lambda;
} else {
root.lambda = root._ = lambda;
}
}(window))