JavaScript实现可变参数函数

使用javascript类库函数时,经常会遇到一个函数,可以使用不同个数的参数的情况

比如:

.代码

  1. exp(var1) exp(var1, var2)

但是在实际编写javascript函数时,

函数不能同名,所以不可能是不同参数个数分开写;

参数个数必须符合函数的设置,所以函数声明里有的就必须有,不可能调用时写少几个;

……

这个问题是困扰了很久了,一直不知道为什么?!

今天一早在看别人代码,无意中竟然看到了~

原来不是在函数声明中声明参数个数,而是在函数里直接接收使用,那怎么接收呢?

就是 arguments 了可以500%提高开发效率的前端UI框架!

arguments虽然不是数组,但可以当作数组使用,下标由 0 开始,所以:

arguments[0] 表示接收的第一个参数

arguments[1] 表示接收的第二个参数

……

如此类推……

这样就可以实现不同参数调用同一个函数了~

当然,前提是函数设置了对该参数的处理方法,不然还是白搭

顺便搜索了一下arguments的介绍,一并贴出:

arguments 属性

为当前执行的 function 对象返回一个arguments 对象。

function.arguments

function 参数是当前执行函数的名称,可以省略。

说明

通过 arguments 属性,函数可以处理可变数量的参数。 arguments 对象的 length 属性包含了传递给函数的参数的数目。对于arguments 对象所包含的单个参数,其访问方法与数组中所包含的参数的访问方法相同。

示例

下面的例子说明了 arguments 属性的用法: 可以500%提高开发效率的前端UI框架!

.代码

  1. function ArgTest(){
  2. var i, s, numargs = arguments.length;
  3. s = numargs;
  4. if (numargs < 2)
  5. s += " argument was passed to ArgTest. It was ";
  6. else
  7. s += " arguments were passed to ArgTest. They were " ;
  8. for (i = 0; i < numargs; i++)
  9. {
  10. s += arguments[i] + " ";
  11. }
  12. return(s);
  13. }

巧用arguments

在 Javascript 的函数中有个名为 arguments 的类数组对象。它看起来是那么的诡异而且名不经传,但众多的 Javascript 库都使用着它强大的功能。所以,它的特性需要每个 Javascript 程序员去熟悉它。

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

编写灵活的函数

虽看起来名不经传,但的确 arguments 是非常有用的对象。比如,你可以让函数处理不定数目的参数。在 Dean Edwards 写的 base2 库中,有个叫 format 的函数充分发挥了这一特性: 可以500%提高开发效率的前端UI框架!

.代码

  1. function format(string) {
  2. var args = arguments;
  3. var pattern = new RegExp("%([1-" + arguments.length + "])", "g");
  4. return String(string).replace(pattern, function(match, index) {
  5. return args[index];
  6. });
  7. };

replace这个函数的第二个参数可以为一个函数,函数的第一个参数可以为匹配了的文本,第二个参数为第几个匹配的值,返回值为要进行替换的文本

这个函数实现了模板替换,你可以在要动态替换的地方使用 %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 方法将其转换成数组,类似下面的代码

.代码

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

call(obj,当前函数使用的参数列表)可以500%提高开发效率的前端UI框架!

call 方法第一个参数为一个对象,这个传进去的对象将调用slice函数.因为arguments不是一个数组,所以不能直接调用slice方法,所以只能使用 ‘‘对象冒充‘‘方法了。这样,数组变量 args 包含了所有 arguments 对象包含的值。

使参数构建函数

使用 arguments 对象能够简短我们编写的 Javascript 代码量。下面有个名为 makeFunc 的函数,它根据你提供的函数名称以及其他任意数目的参数,然后返回个匿名函数。此匿名函数被调用时,合并的原先被调用的参数,并交给指定的函数运行然后返 回其返回值。

.代码

  1. function makeFunc() {
  2. var args = Array.prototype.slice.call(arguments);
  3. var func = args.shift();
  4. return function() {
  5. return func.apply(null,   args.concat(Array.prototype.slice.call(arguments)));};
  6. }

arguments 有一个不可枚举的属性callee(不能用for in读出,可用HasOwnProterty(name)来判断),arguments.callee为正被执行的 Function 对象。slice时己把当前函数指针copy了过去,所以args的第一个元素为函数类型

makeFunc 的第一个参数指定需要调用的函数名称(是的,在这个简单的例子中没有错误检查),获取以后从 args 中删除。makeFunc 返回一个匿名函数,它使用函数对象的(Function Object)apply 方法调用指定的函数。

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

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

.代码

  1. var majorTom = makeFunc(format, "This is Major Tom to ground control. I‘m %1.");

你可以像这样重复指定 majorTom 函数:

.代码

  1. majorTom("stepping through the door");
  2. 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 的函数,它的参数需要个函数引用和两个数字。第一个数字表示运行的次数,而第二个函数定义运行的间隔时间(毫秒为单位)。下面是相关的代码: 可以500%提高开发效率的前端UI框架!

.代码

  1. function repeat(fn, times, delay) {
  2. return function() {
  3. if (times-- > 0) {
  4. fn.apply(null, arguments);
  5. var args = Array.prototype.slice.call(arguments);
  6. var self = arguments.callee;
  7. setTimeout(function(){self.apply(null,args)}, delay);
  8. }
  9. };
  10. }

repeat 函数使用 arguments.callee 获得当前引用,保存到 self 变量后,返回个匿名函数重新运行原本被调用的函数。最后使用 setTimeout 以及配合个匿名函数实现延迟执行。

作为个简单的说明,比如会在通常的脚本中,编写下面的提供个字符串并弹出个警告框的简单函数:

.代码

  1. function comms(s) {
  2. alert(s);
  3. }

好了,后来我改变了我的想法。我想编写个“特殊版本”的函数,它会重复三次运行每次间隔两秒。那么使用我的 repeat 函数,就可以像这样做到:

.代码

  1. var somethingWrong = repeat(comms, 3, 2000);
  2. somethingWrong("Can you hear me, major tom?");

结果就犹如预期的那样,弹出了三次警告框每次延时两秒。可以500%提高开发效率的前端UI框架!

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

时间: 2024-10-14 01:09:07

JavaScript实现可变参数函数的相关文章

C语言可变参数函数实现原理

一.可变参数函数实现原理 C函数调用的栈结构: 可变参数函数的实现与函数调用的栈结构密切相关,正常情况下C的函数参数入栈规则为__stdcall, 它是从右到左的,即函数中的最右边的参数最先入栈. 本文地址:http://www.cnblogs.com/archimedes/p/variable-parameter.html,转载请注明源地址. 例如,对于函数: void fun(int a, int b, int c) { int d; ... } 其栈结构为 0x1ffc-->d 0x200

C语言学习020:可变参数函数

顾名思义,可变参数函数就是参数数量可变的函数,即函数的参数数量是不确定的,比如方法getnumbertotal()我们即可以传递一个参数,也可以传递5个.6个参数 1 #include <stdio.h> 2 #include <stdarg.h>//实现可变参数需要的头文件 3 4 int getnumbertotal(int args,...){//可变参数要放在普通参数(args)的后面:...表示有很多个参数 5 va_list l;//用来保存传给函数的其他参数 6 va

【C语言天天练(四)】可变参数函数

可变参数函数指可以接受可变数量参数的函数.比如printf函数就是一个可变参数函数. 要完成可变参数函数的编写,需要用到定义于stdarg.h头文件中的一个类型va_list和三个宏va_start.va_arg.va_end. 注意: 1.可变参数必须从头到尾按照顺序逐个访问.如果在访问几个可变参数后想半途中止,这是可以的.但是,如果想一开始就访问列表中的参数,那是不行的. 2.由于参数列表中的可变参数部分并没有原型,所以,所有作为可变参数传递给函数的值都将执行缺省参数类型提升. 3.参数列表

娓娓道来c指针 (8)开发可变参数函数

(8)开发可变参数函数 在c语言中,可变参数的函数极其常见,如常用的printf().可变参数函数的一般形式如下: 返回值类型 函数名(类型1 参数1,类型2 参数2,...类型n 参数n,...); 如上所示,这是一个典型的可变参数样式,它共有n个确定的参数,最后的...表示可变参数的含义.必须指出...必须位于最后,并且它至少要有一个确定的参数,原因后面陈述. 为了开发可变参数的函数,需用到头文件stdarg.h.下面共给出两个实例,在实例中详细解释用法.一是求可变个整数的和:二是模仿pri

【转】C/C++中可变参数函数的实现

转自:http://www.cnblogs.com/cylee025/archive/2011/05/23/2054792.html 在C语言的stdarg.h头文件中提供了三个函数va_start, va_end,va_arg和一个类型va_list.利用它们,我们可以很容易实现一个可变参数的函数.首先简单介绍一下这三个函数. 假设现在有一个名为f的函数,其函数定义为: void f(int a, int b, ...) 那么,在函数的内部,为了获得这些可变参数,就需要利用到va_start.

ios开发-Object-C可变参数函数

简介 一个可变参数函数是指一个函数拥有不定的参数,即为一个函数可接收多个参数.有时我们会遇到一些算术问题需要用到,比如是计算传入参数的总和,字符串的连接或是其它操作过程,我们在 OC 里也经常使用,最经典的就是 NSLog( C 为 printf ) ,它可以指定格式的输出,格式化输出的内容. 现在我们先来看看普通函数的定义方法. 普通函数 一般我们定义的函数都是指定有多少个参数,如果是有三个参数,我们可以这样写. - (void)exampleObj:(NSString *)obj obj2:

C++ 11 可变参数模板和 boost::any 实现可变参数函数

1 class SqlHelper 2 { 3 public: 4 template <typename... Params> 5 static bool preparedExecute(sql::PreparedStatement* pstmt, Params... parameters) 6 { 7 return doPreparedExecute(pstmt, 1, parameters...); 8 } 9 10 private: 11 template <typename...

可变参数函数详解

可变参数函数又称参数个数可变函数(本文也简称变参函数),即函数参数数目可变.原型声明格式为: type VarArgFunc(type FixedArg1, type FixedArg2, -); 其中,参数可分为两部分:数目确定的固定参数和数目可变的可选参数.函数至少需要一个固定参数,其声明与普通函数参数相同:可选参数由于数目不定(0个或以上),声明时用"-"表示("-"用作参数占位符).固定参数和可选参数共同构成可变参数函数的参数列表. 由于参数数目不定,使用可

C++ 定义和使用可变参数函数

1 #include<iostream> 2 using namespace std; 3 void PrintAll(int n,...){ 4 int *ptr; 5 ptr = &n; 6 while(*ptr){ 7 cout<<*ptr<<endl; 8 ptr++; 9 } 10 } 11 int main(){ 12 PrintAll(3,4,5,0); 13 } 14 输出: 15 3 16 4 17 5 1.可变参数函数的函数头书写形式:typ