码农干货系列【5】--lambda in js:lambda.js 1.0.0发布

2012-12-28 05:55

码农干货系列【5】--lambda in js:lambda.js 1.0.0发布

by 【当耐特】

at 2012-12-27 21:55:00

original http://www.cnblogs.com/iamzhanglei/archive/2012/12/27/2836247.html

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


完整demo下载





欢迎任何问题或者建议。

本文链接