javascript奇异的arguments分析


Posted in Javascript onOctober 20, 2010

在每个函数中,都有个名为 arguments 的变量,它以类似数组的形式保存了当前调用的参数。而它实际上并不是个数组,使用 typeof arguments 语句尝试会返回“object”(对象),所以它不能像 Array 一样使用 push 和 pop 等方法。即便如此,仍然可以使用下标以及长度属性(length)获取它的值。

编写灵活的函数
虽看起来名不经传,但的确 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 标记,然后其余的参数就会依次替换这些地方。例如:

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 对象并不是真正意义上的 Javascript 数组,但是我们可以使用数组的 slice 方法将其转换成数组,类似下面的代码

var args = Array.prototype.slice.call(arguments);

这样,数组变量 args 包含了所有 arguments 对象包含的值。

创建预置参数的函数
使用 arguments 对象能够简短我们编写的 Javascript 代码量。下面有个名为 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 的第一个参数指定需要调用的函数名称(是的,在这个简单的例子中没有错误检查),获取以后从 args 中删除。makeFunc 返回一个匿名函数,它使用函数对象的(Function Object)apply 方法调用指定的函数。

apply 方法的第一个参数指定了作用域,基本上的作用域是被调用的函数。不过这样在这个例子中看起来会有点复杂,所以我们将其设定成 null ;其第二个参数是个数组,它指定了其调用函数的参数。makeFunc 转换其自身的 arguments 并连接匿名函数的 arguments,然后传递到被调用的函数。

有种情况就是总是要有个输出的模板是相同的,为了节省每次是使用上面提到的 format 函数并指定重复的参数,我们可以使用 makeFunc 这个工具。它将返回一个匿名函数,并自动生成已经指定模板后的内容:

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 函数时,它都会使用第一个指定的参数填写已经指定的模板。例如上述的代码返回:
"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.callee 是个非常有用的调用自身的匿名函数。

下面有个名为 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); 
}

好了,后来我改变了我的想法。我想编写个“特殊版本”的函数,它会重复三次运行每次间隔两秒。那么使用我的 repeat 函数,就可以像这样做到:
var somethingWrong = repeat(comms, 3, 2000); 
somethingWrong("Can you hear me, major tom?");

结果就犹如预期的那样,弹出了三次警告框每次延时两秒。

最后,arguments 即便不会经常被用到,甚至显得有些诡异,但是它上述的那些惊艳的功能(不仅仅是这些!)值得你去了解它。

Javascript 相关文章推荐
jquery方法+js一般方法+js面向对象方法实现拖拽效果
Aug 30 Javascript
JQuery 文本框回车跳到下一个文本框示例代码
Aug 30 Javascript
node.js中的fs.rename方法使用说明
Dec 16 Javascript
谷歌浏览器调试JavaScript小技巧
Dec 29 Javascript
jQuery事件绑定on()、bind()与delegate() 方法详解
Jun 03 Javascript
值得分享和收藏的Bootstrap学习教程
May 12 Javascript
jQuery中on绑定事件后引发的事件冒泡问题如何解决
May 25 Javascript
扩展jquery easyui tree的搜索树节点方法(推荐)
Oct 28 Javascript
详解Vue2 无限级分类(添加,删除,修改)
Mar 07 Javascript
Vue Promise的axios请求封装详解
Aug 13 Javascript
Vue中使用canvas方法总结
Feb 12 Javascript
jQuery中getJSON跨域原理的深入讲解
Sep 02 jQuery
超越Jquery_01_isPlainObject分析与重构
Oct 20 #Javascript
理解Javascript_15_作用域分配与变量访问规则,再送个闭包
Oct 20 #Javascript
理解Javascript_14_函数形式参数与arguments
Oct 20 #Javascript
理解Javascript_13_执行模型详解
Oct 20 #Javascript
用jquery与css打造个性化的单选框和复选框
Oct 20 #Javascript
Jquery插件之多图片异步上传
Oct 20 #Javascript
jquery判断checkbox(复选框)是否被选中的代码
Oct 20 #Javascript
You might like
php字符串按照单词进行反转的方法
2015/03/14 PHP
Laravel 5框架学习之Eloquent (laravel 的ORM)
2015/04/08 PHP
通过javascript的匿名函数来分析几段简单有趣的代码
2010/06/29 Javascript
Table冻结表头示例代码
2013/08/20 Javascript
jquery的clone方法应用于textarea和select的bug修复
2014/06/26 Javascript
jquery插件orbit.js实现图片折叠轮换特效
2015/04/14 Javascript
浅谈Javascript中substr和substring的区别
2015/09/30 Javascript
JavaScript中Textarea滚动条不能拖动的解决方法
2015/12/15 Javascript
理解JS绑定事件
2016/01/19 Javascript
jQuery 3.0 的变化及使用方法
2016/02/01 Javascript
JS实时弹出新消息提示框并有提示音响起的实现代码
2016/04/20 Javascript
总结JavaScript的正则与其他语言的不同之处
2016/08/25 Javascript
jquery实现的回旋滚动效果完整实例【附demo源码下载】
2016/09/20 Javascript
BootStrap数据表格实例代码
2017/09/13 Javascript
将jquery.qqFace.js表情转换成微信的字符码
2017/12/01 jQuery
JS中双击和单击事件冲突的解决方法
2018/04/09 Javascript
jQuery简单判断值是否存在于数组中的方法示例
2018/04/17 jQuery
ligerUI的ligerDialog关闭刷新的方法
2019/09/27 Javascript
vue实现鼠标移过出现下拉二级菜单功能
2019/12/12 Javascript
javascript实现时间日期的格式化的方法汇总
2020/08/06 Javascript
[16:01]夜魇凡尔赛茶话会 第二期01:你比划我猜
2021/03/11 DOTA
Python3网络爬虫之使用User Agent和代理IP隐藏身份
2017/11/23 Python
python字符串Intern机制详解
2019/07/01 Python
一行Python代码过滤标点符号等特殊字符
2019/08/12 Python
详解opencv中画圆circle函数和椭圆ellipse函数
2019/12/27 Python
HTML中meta标签及Keywords
2020/04/15 HTML / CSS
澳大利亚网上玩具商店:Mr Toys Toyworld
2018/03/25 全球购物
Melissa鞋马来西亚官方网站:MDreams马来西亚
2018/04/05 全球购物
商务专员岗位职责
2013/11/23 职场文书
西北政法大学自主招生自荐信
2014/01/29 职场文书
调解员先进事迹材料
2014/02/07 职场文书
团委书记的竞聘演讲稿
2014/04/24 职场文书
2014年“向国旗敬礼”网上签名寄语活动方案
2014/09/27 职场文书
个人作风纪律整顿整改措施
2014/10/25 职场文书
教育教学工作反思
2016/02/24 职场文书
Java面试题冲刺第十八天--Spring框架3
2021/08/07 面试题