请选择 进入手机版 | 继续访问电脑版
收藏本站腾讯微博新浪微博
点点网模板设计大赛 phpchina

经典论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

蓝色理想 最新研发动态 用悬赏 三天解决问题 解决访问速度慢 论坛支持农历生日 - 给官方提建议

论坛活动及任务 归纳网站最新活动 地图任务 邮件更新任务:保护帐号安全

积分换实物,来参加蓝色理想积分兑换吧! 联系招聘客服 蓝色理想帮你找工作! 万元奖励等你拿——点点网模板设计大赛

查看: 3529|回复: 5

【译】javascript一怪——arguments对象 [复制链接]

zcfg 楼主
帖子
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 人评分威望 收起 理由
cloudgamer + 1 谢谢分享

总评分: 威望 + 1   查看全部评分

西部数码顶级域名注册商39元抢注!
帖子
38
体力
95
威望
0
居住地
安徽省 合肥市
发表于 2010-5-16 13:25:39 |显示全部楼层
不错,学了几招!
租服务器,上51IDC | [长沙]招聘:PHP经理10K/WEB前端6K/PHP开发6K

使用道具 举报

帖子
756
体力
1819
威望
0
居住地
浙江省 杭州市
发表于 2010-5-16 14:17:00 |显示全部楼层
学习了,谢谢楼主

使用道具 举报

小秦

版主 手机认证 

帖子
2884
体力
6706
威望
12
居住地
河南省 平顶山市
发表于 2010-5-16 14:31:47 |显示全部楼层
正文的第一句翻译的就有问题:
arguments是一种本地、类数组的对象的名称

什么叫本地的?
我想英文的原文应该是 local,在这如果翻译成中文的话,应该是局部才对嘛.

使用道具 举报

bound0 

老饕

版主 手机认证 

帖子
6592
体力
8775
威望
287
发表于 2010-5-16 14:37:31 |显示全部楼层

回复 4# faeng220 的帖子

嗯。“本地” 一般是指 native ,也可以说成是“原生的”。这里原文确实是local。

[ 本帖最后由 bound0 于 2010-5-16 14:39 编辑 ]
[Bound0 专题列表]
Pas besoin de gril : l'enfer, c'est les Autres.

使用道具 举报

我佛·山人

荣誉管理 手机认证 

帖子
2368
体力
22823
威望
85
居住地
北京市 朝阳区
发表于 2010-5-16 23:03:03 |显示全部楼层
创建预置参数的函数
应该叫柯里化
http://baike.baidu.com/view/2804134.html?tp=1_00

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

Archiver|手机版|安久科技提供CDN|blueidea.com ( 京ICP备05002321号 )  

GMT+8, 2012-2-11 04:39 , Processed in 0.065232 second(s), 9 queries , Gzip On, Memcache On.

Powered by Discuz! X2

© 2001-2011 Comsenz Inc.

回顶部