ECMAScript[Effective JavaScript 笔记]第22长:使用arguments创建而更换参数的函数

第21漫长讲述使用可转换参数的函数average。该函数而处理任意数量的参数并回这些参数的平均值。

什么样创建而更换参数的函数

1、实现稳元数的函数

书写上的本

function averageOfArray(a){
    for(var i=0,sum=0,n=a.length;i<n;i++){
        sum+=a[i];
    }
    return sum/n
}

以ES5 Array.reduce方法的版

function averageOfArrayES5(a){
    if({}.toString.call(a) !== '[Object Array]')a=[].slice.call(a);
    var n=a.length;
    var sum=a.reduce(function(prev,cur){return prev+cur;});
    return sum/n;
}

调用方法

averageOfArray([2,7,1,8,3,4,5]);

averageOfArray函数定义了一个形参,即参数列表中之变量a。当调用函数averageOfArray时,只待提供单个参数,即数字数组。

2、利用arguments实现而换元数函数

运用js的一个事实,即给每个函数都隐式地提供了一个名为arguments的片变量。arguments对象是一个类数组。它吗每个实参提供了一个索引属性,还蕴藏一个length属性用来指示参数的个数。从而可以经合历arguments对象的每个元素来落实而转换元数的函数

function average(){
    for(var i=0,sum=0,n=arguments.length;i<n;i++){
        sum+=arguments[i];
    }
    return sum/n;
}

相同利用ES5
Array.reduce方法的本,这里用对arguments类数组对象转化为实在的对象。我们采用Array.prototype.slice()方法结合之前讲的函数的call方法来拍卖。

代码如下:

var obj={
   "0":100,
   "1":"sdfsafd",
   length:2,
   each:function(){

   }
}
Array.prototype.slice.call(obj);//[100, "sdfsafd"]

下一场将参数对象转化一下

function average(){
    var a=[].slice.call(arguments);
    var sum=a.reduce(function(prev,cur){return prev+cur;});
    return sum/n;
}

注:其中[].slice.call()方法及Array.prototype.slice.call()方法,效果一样。类似之Object.prototype.toString.call()和({}).toString.call()方法。想了解又详细,可以自动检索原型链的连锁知识。

然而更换参数函数提供了灵活的接口。不同之调用者可应用不同数量的参数来调用它们。但它们自己也失去了好几造福。
纪念采取计算数组参数来调用可变换参数的函数,只能使用apply()方法。如果提供了一个利之可变参数的函数,也最好好提供一个亟待展示指定数组的定势元数的版。

3、提供一个轻量级的包裹

function average(){
    return averageOfArray(arguments);
}

此地修了一个轻量级的卷入,并委托给一定元数的版本来兑现可易参数的函数。

贯彻函数的重载

可根据传入参数的情,实现方便的功效。

function doAdd(){
    if(arguments.length==1){
        return arguments[0]+10;
    }else if(arguments.length==2){
        return arguments[0]+arguments[1];
    }
}
doAdd(10);//20
doAdd(30,20);//50

arguments对象和命名参数一起用。 

function doAdd(num1,num2){
    if(arguments.length==1){
        return num1+10;
    }else if(arguments.length==2){
        return num1+num2;
    }
}
doAdd(10);//20
doAdd(30,20);//50

下面的代码对于用jquery的同班应该无会见好陌生。

$('body').css('font-size');
$('body').css('font-size',30);

就此得哪怕是相仿之风味。

对此这面还进行扩展一下。比如根据传入参数的个数与参数的品类,来完成对许不同之效用。jquery里之众多API,都是因此相关的点子来落实之,有趣味之足关押一下jquery的源码。

提示

– 使用隐式的arguments对象实现可更换参数的函数

设想针对可转换参数的函数提供一个外加的稳定元数的版,从而使用者无需借助apply方法。

附录:arguments对象

arguments对象是一个类数组的对象,包含在传播函数中之拥有参数。
脚我们演示看一下,这个arguments对象到底含如何东西。

function a(){
   console.log(arguments);
}
a(1,2,3,6,7);//

博如下的图示

ECMAScript 1

arguments对象属性:

搜索引值 “0”,”1″代表对应参数。

function a(){
   console.log(arguments[3]);
}
a(1,2,3,6,7);//6

length代表参数长度。

function a(){
   console.log(arguments.length);
}
a(1,2,3,6,7);//5

callee是一个指南针指向拥有者arguments对象的函数。

function a(){
   console.log(arguments.callee);
}
a(1,2,3,6,7);//function a(){...}

caller是一个以ES3并不曾概念之性。

以此特性被保留着调用当前函数的函数的援,如果是大局作用域中调用当前函数,它的值为null。

function a(){
   console.log(arguments.caller);
}
a(1,2,3,6,7);//null

每当从严模式下,arguments.callee和arguments.caller都见面报错。
ES5遭受arguments.caller的价老是undefined。
arguments的值永远与相应命名参数的价值保持同。代码示例:

function b(name,age){
   arguments[1]=20;
   return name+'是'+age+'岁!';
}
b('li lie',30);//"li lie是20岁!"
b('han mei mei');//"han mei mei是undefined岁!"

arguments对象的值会自动感应到相应的命名参数达到。所以每次都指向argument[1]的修改,也会见修改age的价,结果她还是20。但眼看并无是说读博就有限单值会访问同一之内存空间;它们的内存空间是单身的,但其的值会同步。
当只传入一个参数时,arguments[1]的价值不见面反射到命名参数中,因为arguments对象的长短是出于传入的参数决定的,不是由于定义函数时的命名参数的个数控制的。此时arguments[1]尽管如此发价,但命名参数是匪会见同步值的。
并未传递值的命名参数将机关为赋undefined值。和概念变量但从没初始化一样。
注意:每当从严模式下本着arguments对象的赋值会更换得不算。就算像面那样arguments[1]=20,age的价值吗非会见改。另外重写arguments对象的价会造成错误(代码不会见尽)。
ECMAScript中的装有参数传递的都是价值,不容许通过引用传递参数。

var a=[1,2,3,4,5];
function b(c){c=[]};
b(a);
a;//[1, 2, 3, 4, 5]