ECMAScript函数参数

关于ECMAScript函数参数的多方面理解

写在前面

无论在哪种编程语言中,函数都是特别有意思的部分,但同时也是一个难点。在ECMAScript中,作为对象的函数也不例外,让人又爱又恨。这一章我们主要从多个方面聊一聊函数参数这一部分,至于函数像海一样深的其他部分我们有机会再聊。

函数的有些知识点是比较简单的,所以在进入正题之前,我们先简单介绍两点:函数的return和函数的重载,因为函数的重载需要arguments的知识,所以我们最后来理解函数的重载。

章节结构如下:

  • 函数的return
  • 函数参数
  • 函数的重载

注:如没有另外说明,文中的函数均是指ECMAScript中的函数。

函数的return

return顾名思义就是返回,函数在执行完return后就会立即停止并返回,就是说,return后面的语句是永远也不会执行的。如下:

function functionReturn(){
    return 'over;
    console.log('something after return');
}

something after return是永远也不会执行的。

注:这里可能会有歧义产生。这里说的return之后是紧接着return之后,像这样是不包括的:

function fn() {
    (function(){
        for(var i in a){
            return(i);
        }
    })();

console.log('hello world');
}

var a = [1, 2, 3];
fn();

这里有return,后面的打印依然可以正常输出,这个应该不难理解。评论里网友韩子迟有提出这个歧义,特此更正,同时也感谢韩子迟的提出。

函数参数

关于函数参数我总结了8点,我们分开来说。

1. 函数对传递进来的参数个数没有限制,对传递进来的参数的数据类型也没有限制。即,如果形参有2个,但是传递进来的实参可以是1个,也可以是3个,而且参数类型也无所谓。

2. 每个函数在被调用的时候,其活动对象会获得两个特殊的变量,其中之一就是arguments对象,在arguments对象中保存着传递给函数的参数,在函数体内可以通过arguments对象来访问这个参数数组,从而可以获得每一个实参,但是要注意的是,arguments对象只是与数组类似的一个对象,它并不是Array的实例。

看个例子:

function funcAdd(num1,num2){
    console.log(num1+num2);
    console.log(arguments);
}
funcAdd(100,200);

调用funcAdd函数的时候,实参被保存在arguments对象中,所以打印结果为300[100,200]。我们可以像访问数组一样访问arguments对象,如下:

function funcAdd(num1,num2){
    console.log(num1+num2);
    console.log(arguments[0],arguments[1],arguments[2]);
}
funcAdd(100,200);

因为只传递了两个参数,所以打印结果为,100200undefined

3. 由上面的例子,还可以得出:没有传递值的命名参数将赋值为undefined

4. 命名参数(叫形参应该好理解一些)不是必须的。

如下:

function funcAdd(){
    console.log('传递给函数的两个参数是:'+arguments[0]+'和'+arguments[1]);
}
funcAdd(1,'para2');

在这个函数中,并没有显式的给出命名参数,而是使用的arguments对象中的前两个值,打印结果是:传递给函数的两个参数是:1和para2,所以命名参数并不是必须的。显式写出命名参数一是习惯使然,二是提供一种视觉上和编程上的便利。

5. 关于命名参数,其他编程语言比如C需要函数签名,即函数名、参数个数、参数类型、返回值等相关声明信息,之后调用函数时必须和函数签名一致,但是ECMAScript中的函数没有函数签名。这一点在下面的函数的重载中会有介绍。同时,也正是因为没有ECMAScript没有函数签名,所以函数不能实现重载。

6. 函数的arguments对象有一个length属性,可以看成是数组的长度(arguments对象只是与数组类似的一个对象,它并不是Array的实例),从而获取传递给函数的参数的个数

如下:

function funcAdd(){
    console.log(arguments.length);
}
funcAdd();
funcAdd(1);
funcAdd(1,2);

这段代码只是打印出调用函数时传递给函数的参数个数,打印结果为:0``1``2(之前写的是123,特此更正)。

7. 命名参数的值永远和arguments中的值(arguments中有值)保持同步,这是单向的,即arguments中的值会使命名参数的值同步。

如下:

function funcAdd(num1,num2){
    arguments[0]=20;
    console.log(num1+num2);
}
funcAdd(10,10);

打印结果是:30。因为对于命名参数和arguments,函数调用的是arguments。只是一般情况下有一个命名参数的值会保存到arguments中的过程而已。

注:虽然命名参数的值永远和arguments中的值(arguments中有值)保持同步,但是它们的内存空间是独立的,并不共用同一个内存空间,只是结果两个值会同步而已。

8. ECMAScript中的所有参数传递都是按值传递,访问变量有按值访问和按引用访问两种方式。

首先说一下基本类型的复制。基本类型的复制是完全独立的,比如value1=value2,在这里将value2的值复制给了value1,这两个值是完全独立的,随意修改其中一个,另一个值是不会发生改变的。

但是引用类型的复制就不一样了,和基本类型的复制不同的是,引用类型复制的是指针,这个指针指向的都是堆内存中的同一个对象,所以,如果修改一个复制的变量,另一个变量也会跟着发生变化。

var o1=new Object(),o2=o1;
o1.color='red';
o2.color='blue';
console.log(o1.color);
console.log(o2.color);

因为o1o2引用的是同一个对象,所以修改其中一个引用,另一个跟着变化。所以打印结果分别为:blue``blue

接下来说值的传递。

基本类型值的传递和基本类型变量的复制一个道理,引用类型值的传递和引用类型值的复制一样,只是复制引用,对于函数来说,把函数外面的值传递给函数内部,就是把函数外部的值复制给函数内部,和一个变量复制一个变量的道理一样。

有了函数参数的一些理论,下面聊一聊函数重载。

没有重载

函数的重载是指函数名相同,但是形参列表(参数的个数、参数的数据类型)不相同。在其他编程语言比如C++(之前写的是C,C没有重载,特此更正)中,重载是可以实现的,但是在ECMAScript中,函数是没有重载的。先看一段代码:

function funcAdd(num1,num2){
    console.log(num1+num2);
}

function funcAdd(num){
    console.log(num);
}

funcAdd(100,200);
funcAdd(100);

在ECMAScript中,位于后面的同名函数会覆盖前面的函数,所以最终调用的函数是funcAdd(num),在执行console.log(funcAdd(100,100));是,因为调用的函数形参只有一个,传入arguments的是两个参数100200,即arguments[0]的等于100,arguments[1]的等于200,但是函数调用时只传递arguments[0],为了验证我们单独看下面一段代码:

function funcAdd(num){
    console.log(num);
    console.log(arguments);
}

funcAdd(100,200);

打印结果为100[100,200],验证了上面的结论。

虽然没有重载,但是我们可以来模拟重载机制,即可以来检测数据长度和数据类型,从而执行不同的代码来模拟重载的实现。我们简单写一段代码:

function funOverride(){
    if(arguments.length==1){
        console.log('Hi, '+arguments[0]+'.');
    }else{
        console.log('Please input one para.');
    }
}
funOverride();
funOverride('Jim');

在这里,我们分别判断实参的个数从而决定不同的输出,这在某种程度上模拟了重载。当然,这只是一段简单的代码,要完全实现重载还差的很多。

小结

关于ECMAScript中的函数参数就先说到这里,如果大家对本文有什么建议意见,还请大家不吝指出,同时也欢迎大家在评论里讨论。


转载请记得说明作者和出处哦-.-
作者:myvin
原文出处:http://www.cnblogs.com/myvin/p/4760195.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值