JavaScript具有类似Lambda表达式编程能力的代码(改进版)


Posted in Javascript onSeptember 14, 2010

在发了博文之后,我又花了一些时间尝试解决这个问题……经过几次尝试之后,我找到了另一种pattern,括号并不再是必要的了:

eval(function () { 
var s = '', ww = [v] > (s += v); 
var ws = [n] > ww(' <A href="#">(' + n + ')</A> '); 
pnView3(14, [n] > ww(' [' + n + '] '), 
1, 37, 
ws, [] > ww(' ... '), 
2, 1 
); 
document.write(s); 
} .lamda0());

不过,由于运算符优先级的关系,比较、门、赋值等运算符仍然不能直接写在(伪)Lambda表达式中。
也就是说
function(a, b){ a == b }

仍然需要写成
[a, b] > (a == b)

另外,选择的pattern本身是具有实际效果的——当把一个数组和另一样东西进行比较的时候,脚本引擎会先尝试把两边都转化成数值,如果不成功就转化成字符串再比较。
不过我想正常情况下应该很少有人会拿数组跟别的东西这么比——所以甚至不需要主动去避免,只要用不到(伪)Lambda表达式的时候不特意去这样用就没问题了。

新的实现代码如下:

/*! 
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再次抽疯,这次还是没有下载。

Javascript 相关文章推荐
JS 面向对象之神奇的prototype
Feb 26 Javascript
jQuery中绑定事件的命名空间详解
Apr 05 Javascript
javascript中创建对象的几种方法总结
Nov 01 Javascript
JQuery判断HTML元素是否存在的两种解决方法
Dec 26 Javascript
基于iframe实现类似于ajax的页面无刷新
May 31 Javascript
jQuery使用经验小技巧(推荐)
May 31 Javascript
微信小程序 rpx 尺寸单位详细介绍
Oct 13 Javascript
vue2+el-menu实现路由跳转及当前项的设置方法实例
Nov 07 Javascript
Angular4 ElementRef的应用
Feb 26 Javascript
vue中通过使用$attrs实现组件之间的数据传递功能
Sep 01 Javascript
jQuery实现简单飞机大战
Jul 05 jQuery
微信小程序向Java后台传输参数的方法实现
Dec 10 Javascript
手把手教你自己写一个js表单验证框架的方法
Sep 14 #Javascript
(jQuery,mootools,dojo)使用适合自己的编程别名命名
Sep 14 #Javascript
修改jquery里的dialog对话框插件为框架页(iframe) 的方法
Sep 14 #Javascript
基于jquery的划词搜索实现(备忘)
Sep 14 #Javascript
基于jquery的页面划词搜索JS
Sep 14 #Javascript
基于Jquery的实现回车键Enter切换焦点
Sep 14 #Javascript
js输出列表实现代码
Sep 12 #Javascript
You might like
《一拳超人》埼玉一拳下去,他们存在了800年毫无意义!
2020/03/02 日漫
一个简洁的多级别论坛
2006/10/09 PHP
php 执行系统命令的方法
2009/07/07 PHP
分享下php5类中三种数据类型的区别
2015/01/26 PHP
微信小程序 消息推送php服务器验证实例详解
2017/03/30 PHP
JS IE和FF兼容性问题汇总
2009/02/09 Javascript
javascript 关于# 和 void的区别分析
2009/10/26 Javascript
使用AOP改善javascript代码
2015/05/01 Javascript
CKEditor无法验证的解决方案(js验证+jQuery Validate验证)
2016/05/09 Javascript
AngularJS基础 ng-focus 指令简单示例
2016/08/01 Javascript
微信小程序Redux绑定实例详解
2017/06/07 Javascript
vue-router路由与页面间导航实例解析
2017/11/07 Javascript
Vue 中axios配置实例详解
2018/07/27 Javascript
微信小程序全局变量功能与用法详解
2019/01/22 Javascript
express.js中间件说明详解
2019/03/19 Javascript
详解微信小程序网络请求接口封装实例
2019/05/02 Javascript
vue中$refs, $emit, $on, $once, $off的使用详解
2019/05/26 Javascript
怎么使用javascript深度拷贝一个数组
2019/06/06 Javascript
Vue 2.0 侦听器 watch属性代码详解
2019/06/19 Javascript
vue实现选中效果
2020/10/07 Javascript
在python3环境下的Django中使用MySQL数据库的实例
2017/08/29 Python
python日期时间转为字符串或者格式化输出的实例
2018/05/29 Python
Numpy数据类型转换astype,dtype的方法
2018/06/09 Python
django的ORM操作 增加和查询
2019/07/26 Python
Django ORM 自定义 char 类型字段解析
2019/08/09 Python
详解pyinstaller生成exe的闪退问题解决方案
2020/06/19 Python
从Pytorch模型pth文件中读取参数成numpy矩阵的操作
2021/03/04 Python
客房主管岗位职责
2013/12/09 职场文书
继承权公证书
2014/04/09 职场文书
材料物理专业求职信
2014/09/01 职场文书
广告设计专业毕业生自我鉴定
2014/09/27 职场文书
房产转让协议书(2014版)
2014/09/30 职场文书
圆明园纪录片观后感
2015/06/03 职场文书
golang如何去除多余空白字符(含制表符)
2021/04/25 Golang
如何利用pygame实现打飞机小游戏
2021/05/30 Python
简单总结SpringMVC拦截器的使用方法
2021/06/28 Java/Android