码农干货系列【5】--lambda in js:lambda.js 1.0.0发布
2012-12-27 21:55 【当耐特】 阅读(6565) 评论(3) 编辑 收藏 举报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下载
欢迎任何问题或者建议。