但是我后来也跟人说,因为接受的参数太多,所以如果不把智能提示写得很清楚的话,连我自己都常常搞不清楚该怎么用。
不过,接受参数多,除了容易弄错用法以外,还会产生另一个问题,这也是我编写出今天发布的这个东西的原因。
来看一下JS版的页码呈现组件的完全版函数签名:
复制代码 代码如下:
function pnView(
currentPage, actionCurrent,
beginPage, endPage,
actionBegin, actionEnd,
currentSiblings, actionCurrentSibling,
preventFolding, actionFolding,
endOfBegin, beginOfEnd,
actionBeginSibling, actionEndSibling
)
可以看到,这个可以最大幅度进行自定义的完全版函数签名,接受14个参数,而其中有一半——也就是7个参数,是要接受回调函数的。
由此产生的问题就是需要手工写入多次的“function(){}”等字符组合,就像这样:
复制代码 代码如下:
function ww(s) { document.write(s); }
function ws(n) { ww(' <A href="#">(' + n + ')</A> '); }
pnView(14, function (n) { ww(' [' + n + '] ') },
1, 27,
function (n) { ww('<A href="#">|< ' + n + '</A> '); }, function (n) { ww(' <A href="#">' + n + ' >|</A>'); },
2, ws,
1, function () { ww(' ... '); },
2, 2,
ws, ws
);
当我在网页中测试这个组件的时候我就觉得自己非常想念C#中的Lambda表达式——虽然有些人、有些JS框架会把匿名函数称作“Lambda表达式”,但其实那只相当于C#中的“匿名委托/函数”,而Lambda的(表面)特征是使用简短的语法模式来反映一个(回调)函数/过程(或者说动作)的逻辑,而不被“delegate”或者别的什么关键字分散精力。
出于这样的原因,我编写了这个可以转译JS代码、把一种特定的模式(pattern)翻译成函数定义的模块。
在使用这个模块以后,前面的那个调用可以变成这个样子:
复制代码 代码如下:
eval(function () {
var ww = (s, document.write(s));
var ws = (n, ww(' <A href="#">(' + n + ')</A> '));
pnView(14, (n, ww(' [' + n + '] ')),
1, 27,
(n, ww('<A href="#">|< ' + n + '</A> ')), (n, ww(' <A href="#">' + n + ' >|</A>')),
2, ws,
1, (0, ww(' ... ')),
2, 2,
ws, ws
);
}.lamda())();
模块的完整代码如下:
复制代码 代码如下:
/*!
L-amda "a-Lambda", a module provides Alternate "Lambda" style programming ability for JavaScript.
Created By NanaLich. 2010-09-08
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);
//if (!(o instanceof Array)) o = [o];
while (i = o.shift()) {
for (j in a) {
if (!i[n = a[j]]) i[n] = m;
}
}
}
var rx0 = /^\s*(0|NaN|null)\s*,$/;
var rx1 = /([\W]\s*)\((\s*0\s*,|(?:\s*[a-z_$][\w$]*\s*,)+)|"(\\[\s\S]|[^\x22])*"|'(\\[\s\S]|[^\x27])*'/gi;
var rx2 = /\)/g;
function rxGetFlags(rx) { // 取出正则表达式的创建选项
return (rx.global ? 'g' : '') + (rx.ignoreCase ? 'i' : '') + (rx.multiline ? 'm' : '');
//return /\/([gim]*)$/.exec('' + rx)[1];
}
attachEntry(RegExp, ['getFlags'], rxGetFlags);
attachEntry(RegExp.prototype, ['getFlags'], function () {
return rxGetFlags(this);
});
function translateLambda(s) {
if (typeof (s) != 'string') s = '' + s;
var x = new RegExp(rx1.source, rx1.getFlags());
var y = new RegExp(rx2.source, rx2.getFlags()); // 由于firefox、safari等浏览器对全局匹配正则表达式有过度的优化,所以这里采用一种迂回的办法创建不重复的正则表达式实例
var m, l = 0, r = '';
while (m = x.exec(s)) {
var c = m[0], h, p, q, t;
switch (c.charAt(0)) { // 判断期待的语法成分
case '$':
case ')':
case ']':
case '"':
case "'":
continue; // 函数传参,跳过
}
h = m[2];
if (rx0.test(h))
h = '';
else
h = h.substr(0, h.length - 1); // 去掉末尾的逗号
r += s.substring(l, p = m.index); // 在结果字符串上附加之前余留的内容
y.lastIndex = l = p + c.length; // 从逗号之后开始寻找右括号
while (q = y.exec(s)) {
q = q.index;
try {
t = 'return ' + s.substring(l, q) + ';';
new Function(t); // 语法测试
//r += c + 'function(' + h + '){ ' + translateLambda(t) + ' }'; // 翻译里面的内容
r += m[1] + 'function(' + h + '){ ' + translateLambda(t) + ' }'; // 翻译里面的内容
x.lastIndex = l = q + 1; // 下一次查找从括号之后开始
break;
} catch (ex) { }
}
if (!q) l = p; // 说明找不到右括号或者有效的代码,直接附加所有匹配的内容
}
try {
r += s.substr(l);
if (/[\w$]*|"(\\[\s\S]|[^\x22])*"|'(\\[\s\S]|[^\x27])*'/.exec(r)[0] == 'function') // 粗略判断产生的是不是函数(可以应付绝大部分情况)
r = '0,' + r; // 使用这种“怪”形式可以在所有浏览器(包括IE)中得到预期的效果
new Function(r); // 语法测试
return r;
} catch (ex) { // 失败,返回原文
return s;
}
};
var lamdaAliases = ["translateLambda", "lambda", "lamda"];
attachEntry([Function, String], lamdaAliases, translateLambda);
attachEntry([Function.prototype, String.prototype], lamdaAliases, function () {
return translateLambda(this);
});
} ();
如果和C#中的Lambda表达式相比的话,我的这个模块还是有很多不足的,不过现在这个样子已经让我很满意了,至少我不用再写太多的“function”了。
简单来说,这个模块的规格特性是这样的——
优点:
减少编写代码时“function”的出现次数;
使用可以在一般的JavaScript编辑器中正常编辑的语法模式(pattern),直接写在函数体中不会导致语法错误。
局限性:
在任何时候使用这个模块都必须调用转译方法(“translateLambda”、“lambda”或者“lamda”)和eval函数,无法省略;
如果存在一个函数A,不可能通过对A进行处理来达到转译传递至A的参数的目的(也就是说a.lambda()或者类似的操作并不会让a((x, x * 2))等同于a(function(x){ return x * 2; }));
不能包含表达式之外的任何语句、不能包含使用“;”来分隔的多条语句。
缺点:
连续出现的括号可能会让代码变得难以理解;
任何编辑器都无法为Lambda表达式提供语法高亮;
存在错误地转译现有代码的可能性——这个模块选择进行匹配的模式是在正常的代码中没有实用价值、也通常不会出现的模式,如:(x, x * 2)等价于单纯的x * 2、(0, a.method())等价于单纯的a.method(),所以这个缺点影响到实际代码的可能性无限趋近于0。
以下是几种不当的用法:
1、使用这个模块并不会节省很多代码量的时候:本末倒置。
复制代码 代码如下:
eval(function(){ // 不仅没减少代码量,反而还增加了
window.onload = (0, alert('载入完成!'));
}.lambda());
2、对接受参数的函数进行转译处理:之前已经提到过这种情况。
复制代码 代码如下:
eval(somefunction.lambda())((x, x.toString(16))); // somefunction可能会产生预料外的结果,而且收到的参数会是x.toString(16)的结果(如果x在此处并没有被定义过,还会产生一个“变量不存在”的异常),而非一个回调函数。
3、为了使用此模块而规避语法检查:
因为使用的是在JavaScript中有效但无实用价值的语法,所以规避语法检查是完全没有必要的。
复制代码 代码如下:
eval("somefunction((x, x.toString(16)))".lamda()); // 失去了语法检查,可能在运行的时候产生意外
4、在(伪)Lambda中使用过多的操作,甚至多条语句:
在设计这个模块的时候我并没有找出可以使用多条语句且可以通过语法检查的模式(pattern),原因是在Lambda表达式中使用多条语句时,“function”、“return”等几个字符所增加的代码量通常是可以忽略的,这样去使用Lambda表达式本身就属于一种偏离了初衷的做法。
复制代码 代码如下:
eval(function(){ somefunction((x, y.something(x); return x.toString(16))); }.lamda())(); // 语法错误
eval(function(){ somefunction((x, y.something(x), x.toString(16))); }.lamda())(); // 容易产生理解上的歧义
eval(function(){ somefunction((x, ++x)); }.lamda())(); // 简单的表达式可以被接受
最佳使用场合:
现在很多人写JavaScript的时候喜欢把自己的代码都写在一个闭包里面,这样可以避免全局作用域污染问题,就像这样:
复制代码 代码如下:
(function(){
// 所有的代码都放在这里
})();
——而这种“大”闭包正好是使用本模块的最佳场合:
复制代码 代码如下:
eval(function(){ // 括号前增加eval
// 所有的代码都放在这里
}.lamda())(); // 括号里增加.lamda()
昨天codeplex抽疯,代码和release上传总出错。再考虑到这个模块的使用场合比较有限,不适合缺乏JavaScript经验的人使用,所以不另外提供源代码打包下载——有需要的话请直接从文中复制。
相关推荐:
中文润色:提升表达的艺术,打造无懈可击的语言魅力,广告营销推广新思路论文
AI人工智能文章生成器写作新纪元
常用AI工具,高效智能生活
SEO热词:提升网站排名的关键秘诀,一句话营销推广怎么写好
ChatGPT的破解版:AI世界的新突破,ai无禁忌
SEO优化攻略:如何通过精准策略提升网站排名与流量,aI ow翻译
自动生成文章的AI软件,助力内容创作的未来
SEO本站:提升网站流量与排名的秘密武器,荆门专业的抖音seo
ChatGPT全球宕机:人工智能的崩塌与未来的挑战,中国ai和美国ai教父
亚马逊的seo是什么阿,亚马逊seo项目 ,中考用ai写作会判0分吗
用AI生成的文章算原创吗?深度解析AI写作背后的秘密
SEO用户:如何为您的网站带来持续流量和转化,惠州网站推广哪个好
ChatGPT:打破语言障碍,理解与沟通的新时代,交通轨道ai
ChatGPT无服务:如何突破限制,未来人工智能的新可能,ai绘制装饰画
SEO走动:提升网站流量的关键一步,SEO数据监控宝宝推荐
WP原创:打造属于你的独特网站,从这里开始!,一个网站推广一个月需要多少钱
SEO百度优化:让你的品牌在搜索引擎中脱颖而出,日照网站推广策划
代哥SEO-让您的网站迅速登顶搜索引擎的秘密武器,济南关键词的排名优化
优化网站的秘诀:提高网站速度与用户体验,助力业务腾飞,旅游网站建设步骤
ChatGPT当前不可用?如何应对AI服务中断的挑战,ai文章免费写作app
为什么“360收录”是你网站推广的必备利器,seo亚马逊
SEO项目:如何通过精确优化提升企业网站排名与转化率,武汉做网站优化的公司
ChatGPT页面无法翻阅?带你深度了解背后的原因与解决方案,pdf怎么转换ai文字
ChatGPT页面打不开怎么办?这些解决方法让你轻松访问AI助手!,分散ai
2024年AI写文章生成器推荐:让创作轻松高效,提升写作水平
SEO广告:如何借助SEO提升品牌曝光与销售业绩?,网站推广怎么选择
为什么做seo矩阵项目,为什么做seo矩阵项目不能做 ,怎么用ai写作
为什么选择SEO会员服务,让您的网站流量飞速增长,靖边专业网站建设公司
seo词库优化,搜索词条优化 ,ai点选择
“关键词指白”:揭秘如何通过精准关键词优化实现流量暴增,全面分析网站seo
UCMS:引领智慧医疗新时代,打造数字化健康未来,推广工作谈营销
什么是seo伪原创,seo就业前景伪原创怎么写 ,头像ai画怎么弄
什么是seo网络推广,seo网络推广技术 ,ai写真官方
seo跟sem是什么,seo和sem的概念 ,惠威的ai功能
Chatget免费网站版无需登录,畅享无限对话体验!,工业 Ai 视觉检测
SEO目的:如何通过精准优化提高网站流量与转化率,百度推广网站关键词
360AI写作怎样?助力创作的新风尚,ai到访
互联网快排:助力企业网站流量爆发的秘密武器,西安网站建设找资源公司
AI助手Stut:智能时代的创新引擎,开启未来工作新篇章,ai对ai的格斗游戏
《收录情况:数字时代的网络信息检索与价值体现》,山东全域营销推广软件客服电话
ChatGPT发生故障,背后隐藏着哪些不为人知的原因与挑战?,硬件ai和软件ai
wordpress seo是什么,wordpress建站seo好做吗 ,学习图文ai
SEO优化公司一般怎么优化?揭秘专业SEO服务的操作流程,人工智能ai写作软件 哪一个好
SEO要点:提升网站排名的核心技巧与策略,福田市网站建设推广费用
什么是seo网站推广,什么是seo网站推广 ,ai酷男人
文字写作AI生成工具:让创作更简单、更高效
seo网站是什么找行者SEO,seo分析网站 ,ai图文梅花
seo需要做些什么,做seo的 ,超级ai地图
文章AI生成软件高效创作新纪元
SEO知道:让你的网站在搜索引擎中脱颖而出,水安建设集团网站