JavaScript⾥function函数实现可变参数(多态)
使⽤javascript类库函数时,经常会遇到⼀个函数,可以使⽤不同个数的参数的情况
⽐如:exp(var1) exp(var1, var2)
但是在实际编写javascript函数时,
函数不能同名,所以不可能是不同参数个数分开写;
参数个数必须符合函数的设置,所以函数声明⾥有的就必须有,不可能调⽤时写少⼏个;
……
这个问题是困扰了很久了,⼀直不知道为什么?!
今天⼀早在看别⼈代码,⽆意中竟然看到了~
原来不是在函数声明中声明参数个数,⽽是在函数⾥直接接收使⽤那怎么接收呢?
就是 arguments 了
arguments虽然不是数组,但可以当作数组使⽤,下标由 0 开始,所以:
arguments[0] 表⽰接收的第⼀个参数
arguments[1] 表⽰接收的第⼆个参数
……
如此类推……
这样就可以实现不同参数调⽤同⼀个函数了~
当然,前提是函数设置了对该参数的处理⽅法,不然还是⽩搭
顺便搜索了⼀下arguments的介绍,⼀并贴出:
引⽤内容引⽤内容
arguments 属性
为当前执⾏的 function 对象返回⼀个arguments 对象。
function.arguments
function 参数是当前执⾏函数的名称,可以省略。
说明
通过 arguments 属性,函数可以处理可变数量的参数。 arguments 对象的 length 属性包含了传递给函数的参数的数⽬。对于arguments 对象所包含的单个参数,其访问⽅法与数组中所包含的参数的访问⽅法相同。
⽰例
下⾯的例⼦说明了 arguments 属性的⽤法:
function ArgTest(){
var i, s, numargs = arguments.length;
s = numargs;
if (numargs < 2)
s += " argument was passed to ArgTest. It was ";
else
s += " arguments were passed to ArgTest. They were " ;
for (i = 0; i < numargs; i++)
{
s += arguments[i] + " ";
}
return(s);
}
巧⽤arguments
在 Javascript 的函数中有个名为 arguments 的类数组对象。它看起来是那么的诡异⽽且名不经传,但众多的Javascript 库都使⽤着它强⼤的功能。所以,它的特性需要每个 Javascript 程序员去熟悉它。
在每个函数中,都有个名为 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];
});
};
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 ⽅法将其转换成数组,类似下⾯的代码
var args = Array.prototype.slice.call(arguments);
call(obj,当前函数使⽤的参数列表)
call ⽅法第⼀个参数为⼀个对象,这个传进去的对象将调⽤slice函数.因为arguments不是⼀个数组,所以不能直接调⽤slice⽅法,所以只能使⽤ ''对象冒充''⽅法了。这样,数组变量 args 包含了所有 arguments 对象包含的值。
使参数构建函数使⽤ arguments 对象能够简短我们编写的 Javascript 代码量。下⾯有个名为 makeFunc 的函数,它根据你提供的函数名称以及其他任意数⽬的参数,然后返回个匿名函数。此匿名函数被调⽤时,合并的原先被调⽤的参数,并交给指定的函数运⾏然后返回其返回值。
function makeFunc() {
var args = Array.prototype.slice.call(arguments);
var func = args.shift();
return function() {
return func.apply(null,  at(Array.prototype.slice.call(arguments)));};
}
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 这个⼯具。它将返回⼀个匿名函数,并⾃动⽣成已经指定模板后的内容:
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 即便不会经常被⽤到,甚⾄显得有些诡异,但是它上述的那些惊艳的功能(不仅仅是这些!)值得你去了解它。
undefined ≠ nullnull 是⼀个对象,undefined是⼀个属性、⽅法或变量。存在null是因为对象被定义。如果对象没有被定义,⽽测试它是否是null,但因为没有被定义,它⽆法测试到,⽽且会抛出错误。
if (myObject !== null && typeof(myObject) !== 'undefined') {
//如果myObject是undefined,它不能测试是否为null,⽽且还会抛出错误
javascript的特性
}
if (typeof(myObject) !== 'undefined' && myObject !== null) {
//处理myObject的代码
}

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。