日期:2014-05-16  浏览次数:20359 次

js中为何没有重载
1.理解参数

JavaScript函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。也就是说,即便你定义的函数只接收两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传递参数。你肯定在疑问为什么会这样?

原因在于JavaScript中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。如果这个数组中不包含任何元素,无所谓;如果包含多个元素,也没问题。实际上,在函数体内可以通过arguments对象来访问这个参数数组,从而获取传递给参数的每一个参数。

例1:
function howManyArgs(){
    alert(arguments.length);
}

howManyArgs("string",45);//2
howManyArgs();//0
howManyArgs(12);//1


这也说明了JavaScript函数的一个重要特点:命名的参数只提供便利,但不是必须的。

关于arguments的行为,还有一点比较有意思。那就是它的值永远与对应命名参数的值保持同步。

例2:
function doAdd(num1,num2){
    arguments[1]=10;
    alert(arguments[0]+num2);
}

doAdd(30,30);//40

因为arguments对象中的值会自动反映到对应的命名参数,即修改arguments[1],也就修改了num2.另外因为arguments的长度是由传入的参数个数决定的,不是由定义函数时的命名参数的个数决定的。即如果只传入一个参数,num2的值为undefined,那么为arguments设置的值不会反映到命名参数中。

2.没有重载

在java中,可以为一个函数编写两个定义,只要这两个定义的签名(接受的参数的类型和数量)不同即可,但在JavaScript中,函数没有签名,因为其参数是由半酣零或多个值的数组来表示的。而没有函数签名,真正的重载是不可能做到的。

如果在JavaScript中定义了两个名字相同的函数,则改名字只属于后定义的函数。
例3:
function addNum(tmp1)
{
    alert(tmp1+100);
}

function addNum(tmp1,tmp2)
{
    alert(tmp1+200);
}

addNum(100);//300


3.没有重载(深入理解)

函数实际上是对象,每个函数都是Funciton类型的实例,而且都与其他类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定。

var sum = new Function("num1","num2","return num1+num2");//不推荐


这是一种定义函数的方式——使用Function的构造函数,最后一个参数始终被看成函数体。但是不推荐使用这种定义方式,因为会导致解析两次代码:第一次是解析常规的JavaScript代码,第二次是解析传入构造函数中的字符串,从而影响性能。不过,这种语法对于理解"函数时对象,函数名是指针"的概念导师非常直观的。

由于函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同。换句话说,一个函数可能会有多个名字。
例4:
function sum(num1,num2){
    return num1+num2;
}  

alert(sum(10,10));//20

var anotherSum =sum;
alert(anotherSum(10,10));//20 

sum=null;
alert(anotherSum(10,10));//20


对例3进行重写,如下:
var addNum = function(tmp1){
    alert(tmp1+100);
};
addNum = function(tmp1,tmp2){
    alert(tmp1+200);
};



通过重写后,很容易看清到底是怎么回事儿——创建第二个函数时,实际上覆盖了引用第一个函数的变量addNum。也可以这样理解,即创建第二个函数后,指针addNum指向了第二个函数,不再指向第一个函数。