[改进]还是那个让JavaScript具有(类似)Lambda表达式编程能力
2010-09-13 13:44 Nana's Lich 阅读(3096) 评论(8) 编辑 收藏 举报在之前的一篇博文中我介绍了一种方法可以让JavaScript具有一种近似于Lambda表达式的编程能力——
但是它有一些缺点,其中妨碍它的使用的最主要的一条就是“多了一层括号,让代码变得难以阅读”。
在发了博文之后,我又花了一些时间尝试解决这个问题……经过几次尝试之后,我找到了另一种pattern,括号并不再是必要的了:
1 2 3 4 5 6 7 8 9 10 11 12 | eval( function () { var s = '' , ww = [v] > (s += v); var ws = [n] > ww( ' <a href="#" rel="noopener nofollow">(' + n + ')</a> ' ); pnView3(14, [n] > ww( ' [' + n + '] ' ), 1, 37, ws, [] > ww( ' ... ' ), 2, 1 ); document.write(s); } .lamda0()); |
不过,由于运算符优先级的关系,比较、门、赋值等运算符仍然不能直接写在(伪)Lambda表达式中。
也就是说
1 | function (a, b){ a == b } |
仍然需要写成
1 | [a, b] > (a == b) |
另外,选择的pattern本身是具有实际效果的——当把一个数组和另一样东西进行比较的时候,脚本引擎会先尝试把两边都转化成数值,如果不成功就转化成字符串再比较。
不过我想正常情况下应该很少有人会拿数组跟别的东西这么比——所以甚至不需要主动去避免,只要用不到(伪)Lambda表达式的时候不特意去这样用就没问题了。
新的实现代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | /*! L-amda "a-Lambda", a module provides Alternate "Lambda" style programming ability for JavaScript. Created By NanaLich. 2010-09-10 This module is published under WTFPL v2, so you just DO WHAT THE Fxxx YOU WANT TO with it. */ ! function () { function attachEntry(o, a, m) { var i, j, n; o = [].concat(o); while (i = o.shift()) { for (j in a) { if (!i[n = a[j]]) i[n] = m; } } } var xx = / "(?:\\[\s\S]|[^\x22])*" | '(?:\\[\s\S]|[^\x27])*' |([^\s\w]\s*)\[(\s*|\s*[A-Z$_][\w$]*\s*(?:,\s*[A-Z$_][\w$]*\s*)*)\]\s*(>)\s*(\(?)/gi; var xy = /[\n\r),;\]}]|$/.source; function rxClone(rx) { return new RegExp(rx.source, (rx.global ? 'g' : '' ) + (rx.ignoreCase ? 'i' : '' ) + (rx.multiline ? 'm' : '' )); } attachEntry(RegExp, [ 'clone' ], rxClone); attachEntry(RegExp.prototype, [ 'clone' ], function () { return rxClone( this ); }); function translateLambda(s) { var m, l = 0, r = '' , x = xx.clone(); // 由于firefox、safari等浏览器对全局匹配正则表达式有过度的优化,所以这里采用一种迂回的办法创建不重复的正则表达式实例 while (m = x.exec(s)) { var h = m[0]; switch (h.charAt(0)) { // 判断期待的语法成分 case '$' : // 函数传参 case ')' : case ']' : case '"' : // 匹配到了字符串 case " '": continue; // 以上皆跳过 } var p, q, t, k = m[4].length, y = new RegExp(k ? ' \\) ' : xy, ' g '); r += s.substring(l, p = m.index); // 在结果字符串上附加之前余留的内容 y.lastIndex = l = p + h.length; // 从伪运算符之后开始寻找右括号或者其它符号 while (q = y.exec(s)) { q = q.index; try { t = ' return ( ' + s.substring(l, q) + ' ); '; new Function(t); // 语法测试 r += m[1] + ' function ( ' + m[2] + ' ){ ' + translateLambda(t) + ' } '; // 翻译里面的内容 x.lastIndex = l = q + k; // 下一次查找从当前边界之后开始 break; } catch (ex) { } } if (!q) l = p; // 说明找不到右括号或者有效的代码,直接附加所有匹配的内容 } try { r += s.substr(l); new Function(r); // 语法测试 return r; } catch (ex) { // 失败,返回原文 return s; } }; var lamdaAliases = ["translateLambda", "lambda", "lamda"]; attachEntry(String, lamdaAliases, translateLambda); attachEntry(String.prototype, lamdaAliases, function () { return translateLambda(this); }); var funPrototype = Function.prototype; attachEntry(Function, lamdaAliases, function (func) { return translateLambda(' 0, ' + func); }); attachEntry(funPrototype, lamdaAliases, function () { return translateLambda(' 0, ' + this); }); var lamda0aliases = [' lambdaInit ', ' lambda0 ', ' lamda0 ']; attachEntry(Function, lamda0aliases, function (func) { return translateLambda(' ! ' + func + ' () '); }); attachEntry(funPrototype, lamda0aliases, function () { return translateLambda(' ! ' + this + ' ()'); }); } (); |
这次为函数增加了专门的方法,去掉了之前蹩足的判断、也增加了新方法稍微简化调用过程;
修正了有额外空格时无法判断期望语法成分的BUG。
另外由于Codeplex再次抽疯,这次还是没有下载。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器