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 相关文章推荐
javascript模仿msgbox提示效果代码
Jun 10 Javascript
node.js中的events.EventEmitter.listenerCount方法使用说明
Dec 08 Javascript
AngularJS基础 ng-model 指令详解及示例代码
Aug 02 Javascript
jquery层级选择器的实现(匹配后代元素div)
Sep 05 Javascript
微信小程序 轮播图swiper详解及实例(源码下载)
Jan 11 Javascript
SpringMVC+bootstrap table实例详解
Jun 02 Javascript
浅谈关于axios和session的一些事
Jul 13 Javascript
微信小程序promsie.all和promise顺序执行
Oct 27 Javascript
JavaScript实现左侧菜单效果
Dec 14 Javascript
Puppeteer环境搭建的详细步骤
Sep 21 Javascript
vue实现登录拦截
Jun 29 Javascript
深入理解Vue的数据响应式
May 15 Vue.js
超越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
追求程序速度,而不是编程的速度
2008/04/23 PHP
ThinkPHP3.1新特性之对页面压缩输出的支持
2014/06/19 PHP
PHP实现的常规正则验证helper公共类完整实例
2017/04/27 PHP
启用OPCache提高PHP程序性能的方法
2019/03/21 PHP
thinkphp5框架调用其它控制器方法 实现自定义跳转界面功能示例
2019/07/03 PHP
laravel实现前后台路由分离的方法
2019/10/13 PHP
ASP中进行HTML数据及JS数据编码函数
2009/11/11 Javascript
jquery实现的让超出显示范围外的导航自动固定屏幕最顶上
2011/09/22 Javascript
javascript获取设置div的高度和宽度兼容任何浏览器
2013/09/22 Javascript
解决html按钮切换绑定不同函数后点击时执行多次函数问题
2014/05/14 Javascript
如何正确使用Nodejs 的 c++ module 链接到 OpenSSL
2014/08/03 NodeJs
IE6-IE9使用JSON、table.innerHTML所引发的问题
2015/12/22 Javascript
JS实现点击网页判断是否安装app并打开否则跳转app store
2016/11/18 Javascript
jQuery遍历节点方法汇总(推荐)
2017/05/13 jQuery
使用Require.js封装原生js轮播图的实现代码
2017/06/15 Javascript
node+express+ejs使用模版引擎做的一个示例demo
2017/09/18 Javascript
浅谈Node Inspector 代理实现
2017/10/19 Javascript
vue项目创建并引入饿了么elementUI组件的步骤
2019/04/11 Javascript
小程序实现短信登录倒计时
2019/07/12 Javascript
layer弹出框确定前验证:弹出消息框的方法(弹出两个layer)
2019/09/21 Javascript
nodejs处理tcp连接的核心流程
2021/02/26 NodeJs
[00:21]DOTA2亚洲邀请赛 Logo演绎
2015/02/07 DOTA
python使用win32com库播放mp3文件的方法
2015/05/30 Python
Python编程之变量赋值操作实例分析
2017/07/24 Python
Python3实现腾讯云OCR识别
2018/11/27 Python
python爬虫开发之selenium模块详细使用方法与实例全解
2020/03/09 Python
Python环境使用OpenCV检测人脸实现教程
2020/10/19 Python
德国黑胶唱片、街头服装及运动鞋网上商店:HHV
2018/08/24 全球购物
教师求职信范文分享
2013/12/27 职场文书
高中生第一学年自我鉴定2015
2014/09/28 职场文书
导游词范文
2015/02/13 职场文书
2015年普法依法治理工作总结
2015/05/26 职场文书
解决golang 关于全局变量的坑
2021/05/06 Golang
Python列表删除重复元素与图像相似度判断及删除实例代码
2021/05/07 Python
如何使用Python实现一个简易的ORM模型
2021/05/12 Python
详解Flask开发技巧之异常处理
2021/06/15 Python