- 在线时间
- 266 小时
- 专家
- 0
- UID
- 312072
- 注册时间
- 2006-12-1
- 帖子
- 169
- 精华
- 0
- 积分
- 337
- 离线
- 452 天
- 帖子
- 169
- 体力
- 341
- 威望
- 5
|
发表于 2008-11-16 23:20:41
|显示全部楼层
在site point上看到篇不错的文章,文章内容并不深入,但感觉很有启发性,周末抽空翻译了下,和大家分享。
水平有限,翻译可能有所偏差,有兴趣的可以去读原文。建议大家还是中英对照着读一读。
原文地址:http://www.sitepoint.com/blogs/2 ... -javascript-oddity/
正文:
--------------------------------------------------------------------------------
arguments是一种本地、类数组的对象的名称,它存在于每个函数中。因为生僻,经常被人们忽略,但却是许多魔术般的程序之源。所有主流js库都汲取了arguments对象的力量。它是每一个javascript程序员都应当熟知的东西。
在任何函数的内部,你都可以通过变量"arguments"访问到它,它是一个包含了该函数被调用时提供的所有实参的“数组”。但事实上,它并不是一个真正的数组——typeof arguments时会返回“object”。你可以通过数字索引(index)的方式来访问arguments中的各个值,它也有和数组一样的length属性,但没有如push和pop之类的数组的方法。
创建灵活的函数
尽管有它的局限性,但arguments仍不失为一个非常有用的对象。例如,你可以创建参数个数不定的函数,如大牛Dean Edwards写的base2这个库中的format方法,秀一下其灵活性:
function format(string) {
var args = arguments;
var pattern = new RegExp("%([1-" + arguments.length + "])", "g");
return String(string).replace(pattern, function(match, index) {
return args[index];
});
};
你提供一个模板字符串,用%1到%9作为占位符加入其中,然后提供最多9个其他的参数用以插入,如:
format("And the %1 want to know whose %2 you %3", "papers", "shirt", "wear");
上面这个句代码会返回字符串“And the papers want to know whose shirt you wear”
你可能已经注意到,在format函数定义时我们只指定了string这一个参数。javascript允许我们给一个函数传递任意多个参数,而不管函数定义时形参是多少个,而且,arguments对象可以访问到所有的实参。
转化为真正的数组
尽管arguments不是一个真正的数组,但使用标准的数组方法slice,我们可以很容易的将它转化一个真正的数组,像这样:
var args = Array.prototype.slice.call(arguments);
args变量现在是一个包含了arguments对象所有值的数组了。
创建预置参数的函数
用arguments对象,我们可以让玩转各种javascript trick。见如下makeFunc函数的定义。这个函数允许你代入一个函数引用和任意数量的参数给它,它会返回一个调用你指定的函数的匿名函数,并在函数被调用时,一并代入预置参数和其它新参数。
function makeFunc() {
var args = Array.prototype.slice.call(arguments);
var func = args.shift();
return function() {
return func.apply(null, args.concat(Array.prototype.slice.call(arguments)));
};
}
代入makeFunc函数的第一个参数是你想调用的函数的引用(是的,在这个简单的例子中未做错误验证。)并且它已从arguments数组中移除。而后,makeFunc返回一个使用Function对象的apply方法的匿名函数,用以调用你指定的那个函数。
apply的第一个参数指向这个函数被调用时的作用域——基本上就是关键字this所指向的被调用的那个函数内部。就现在而言,这个有点高级了,我们就先设为null好了。第二个参数是一组将从该函数(匿名函数)的arguments对象转化而来的值的数组。makeFunc把原始的值的数组和匿名函数代入的arguments数组连结,并将它作为参数代入被调用的函数。
假如说,你想输出一条总是一个样的“模板信息”。为了让你每次调用format函数时,不用不厌其烦的引用该模板文字,你可以使用makeFunc这个实用的函数来返回一个会为你自动调用format函数并填充模板参数的函数:
var majorTom = makeFunc(format, "This is Major Tom to ground control. I'm %1.");
你可以像这样重复调用majorTom函数:
majorTom("stepping through the door");
majorTom("floating in a most peculiar way");
每次调用majorTom函数时,它会调用format函数并代入第一个参数和既定的模板文字。上面的函数将返回:
"This is Major Tom to ground control. I'm stepping through the door."
"This is Major Tom to ground control. I'm floating in a most peculiar way."
创建自引用的函数
你可能认为这些够酷了——等一下,arguments还有一个惊喜给你。它还有另一个有用的属性——callee。arguments.callee包含一个创建arguments对象本身的函数的引用。那么我们如何利用它呢?arguments.callee是一种匿名调用自身的便捷方式。
repeat函数有三个参数——一个函数引用和两个数字。第一个数字指定这个函数被调用多少次,而第二个代表两次调用间的延迟时间(以毫秒计)。下面是repeat函数的定义:
function repeat(fn, times, delay) {
return function() {
if(times-- > 0) {
fn.apply(null, arguments);
var args = Array.prototype.slice.call(arguments);
var self = arguments.callee;
setTimeout(function(){self.apply(null,args)}, delay);
}
};
}
repeat函数通过arguments.callee获得其函数内部的匿名函数的引用,定义为变量self。这样,通过使用setTimeout方法,该匿名函数可在一段延时后再次调用自身。
这里有一个简单得不能再简单的函数,它代入一个字符串并弹出一个包含该字符串的警告框:
function comms(s) {
alert(s);
}
我想创建上面这个函数的特别版本,它重复3次,每次间隔2秒。使用repeat函数,我可以这么做:
var somethingWrong = repeat(comms, 3, 2000);
somethingWrong("Can you hear me, major tom?");
somethingWrong函数的运行结果是:每隔2秒弹出警告窗3次。
arguments虽不常用、有点偏门,但充满惊喜,值得去了解! |
-
总评分: 威望 + 1
查看全部评分
|