![abb0e24700062311fda77826f91a3cf7.png](https://img-blog.csdnimg.cn/img_convert/abb0e24700062311fda77826f91a3cf7.png)
函数的组成
javascript(在下文中简称为js)中函数是一等公民。
函数的组成分为:函数名,函数执行语句体,参数三部分组成,当然函数的参数相对于函数来说是可以存在的,也可以不存在。这里就不卖关子了。
函数的参数
现在主要讨论的就是函数的参数问题。函数的参数我们大致分为:实参与形参。
1.实参:可以粗略的理解成当在调用函数时候需要向函数执行体中传入的指令。
2.形参:可以理解成函数在定义时,需要接受到相关的指令来执行函数体语句的实参指令的占位符。
函数定义参数与传入的参数差异问题
在js中,允许函数定义参数与传入的参数的数量不一致(这也是js灵活的地方与操蛋的地方)。我们知道当传参与定义参不一致的时候,我们就会考虑参数定义的顺序、参数的类型、参数的默认值,参数是否接受到值等一系列问题。
在ES5至以前,我们对于不定数目的参数,使用 arguments 这个类数组(具有length属性的对象)来统一接收函数调用时所传入的所有参数。请看下面例子:
![2aaa302a9a0e6fa98b7fe592c1348cd9.png](https://img-blog.csdnimg.cn/img_convert/2aaa302a9a0e6fa98b7fe592c1348cd9.png)
使用arguments接收函数参数
输出的结果:
![0d51820b215b26ed5c485c0c5945ae5c.png](https://img-blog.csdnimg.cn/img_convert/0d51820b215b26ed5c485c0c5945ae5c.png)
返回的结果
很显然 argument 是不管在函数中是否有定义形参,全部接收在函数调用处传入进来的实参。
ES6对arguments的改变
在函数的定义过程中,是有可能改变形参的值情况出现。当在函数执行体中,我们先改变了形参的值,然后使用 arguments 来读取传入的实参。
![50009925df76f766f6f4a42abc5cdc88.png](https://img-blog.csdnimg.cn/img_convert/50009925df76f766f6f4a42abc5cdc88.png)
改变形参的值
输出的结果为:
![117b6f479bd4fde74ecc96053cadac03.png](https://img-blog.csdnimg.cn/img_convert/117b6f479bd4fde74ecc96053cadac03.png)
arguments的值被改变
很显然的就能看出形参的值在函数执行体中被改变了,arguments的值也会被改变。这样在函数形参值改变之后获取arguments的值是不准确的。因此在es6中不建议使用arguments来获取接收不定数目的参数。
扩展运算符(...)对函数不定参数的影响
上面说到在es6之后不建议使用arguments来进行不定参数的接收之后,应该使用怎么样的一种方式来接收不定参数较为妥当?
在 es6中使用扩展运算符(...)来替代arguments对不定参数的接收。
扩展运算符(...):可以理解成一个默认的遍历器(本章节只讨论扩展运算符对函数参数上的应用)。
![fb95d6518b4ffedc3aa6d432a8c01007.png](https://img-blog.csdnimg.cn/img_convert/fb95d6518b4ffedc3aa6d432a8c01007.png)
扩展运算符接收不定参
输出结果为:
![0c1dc2c7125dee9c9dca7f310f235321.png](https://img-blog.csdnimg.cn/img_convert/0c1dc2c7125dee9c9dca7f310f235321.png)
从输出的结果可以看出扩展运算符会把函数调用传入的参数封装到一个数组中输出。
在函数体语句中我们可以改变...arg的值:
![d24ba4dc2538fe26cb64cbe711529fea.png](https://img-blog.csdnimg.cn/img_convert/d24ba4dc2538fe26cb64cbe711529fea.png)
、
输出结果为:
![505f6b9eeaeb18a68eddb883a323ab2c.png](https://img-blog.csdnimg.cn/img_convert/505f6b9eeaeb18a68eddb883a323ab2c.png)
这样就能够清晰的通过一个显示的变量来接收所有的不定数目的参数。避免在形参值改变之后使用argments来获取传入的实参值。
函数参数的默认值
在定义函数时,通常会给定形参一个默认值,以便当不传实参时,使用默认值来进行替代。现在主要说的是ES6中的默认参数值。
![2c7d42395c1f3ef5ed486abe140f24bf.png](https://img-blog.csdnimg.cn/img_convert/2c7d42395c1f3ef5ed486abe140f24bf.png)
输出的结果为:
![e373e8903a40c7174e712552ce869901.png](https://img-blog.csdnimg.cn/img_convert/e373e8903a40c7174e712552ce869901.png)
明显的看出当不传参数的时候使用的是默认值中的值。
那么问题来了,一般在定义函数参数的使用,不可能把所有的默认参都放在最后面,因为在前面都提到过函数的传入参数和接收参数是可以数目不一致的。在下面的例子中,我们应该如何获取到默认值?
![e3ba6c427a847460287e0348519afc2e.png](https://img-blog.csdnimg.cn/img_convert/e3ba6c427a847460287e0348519afc2e.png)
说到这里了一定会有人说,直接调用foo()就可以获取到a的默认值了。如果你是这样想,你就没有考虑清除,当然这么做是对的,因为示例这样执行是能够得到默认值这个答案的。
稍微得把代码改变一下,你看使用foo()来执行是否可以?
![a17a0f1651bda4a179401178aaf4c8ec.png](https://img-blog.csdnimg.cn/img_convert/a17a0f1651bda4a179401178aaf4c8ec.png)
当然这样执行是不报错的,但是结果是这样的,得不到a的值。这就更加没办法输出a的值了,更加谈不上获取默认值。
![6f3570150c8aef8bab5a688cd0541521.png](https://img-blog.csdnimg.cn/img_convert/6f3570150c8aef8bab5a688cd0541521.png)
针对上面的情况,接下来就是一个从来都在被轻视而且特别重要的问题出现了?什么问题呢?请看下面的大标题。
函数参数的优先级
都听说过运算符的优先级,js中this的优先级。现在来了一个新的概念:函数参数的优先级。
针对上面输出函数参数默认值的问题,在这个时候就可以解决了。
函数参数的优先级:是针对函数调用时候的传入实参的优先级比较,不是针对形参的。
现在我们来改写一下,上面出现问题中的函数调用就可以获取到a的默认值,如下所示:
![096237b16e8259c158c64201af9bee11.png](https://img-blog.csdnimg.cn/img_convert/096237b16e8259c158c64201af9bee11.png)
改写函数调用
把需要获取默认值的形参对应的实参使用undefined来进行传入的时候,我们突然发现。居然可以输出 a = 1。
![3f0d0280c69a3d88ad2a0eaec2312d95.png](https://img-blog.csdnimg.cn/img_convert/3f0d0280c69a3d88ad2a0eaec2312d95.png)
输出结果
是不是觉得特别神奇。当初我也是这么觉得的。
说到这里,发现可以使用undefined 来进行占位,让函数输出其默认值。脑袋里会顺势想到使用null是不是也可以。很显然猜测是最没有底气的。现在我们实际调用来看看。
![4ec4440492c1a366882590b30b01e1b8.png](https://img-blog.csdnimg.cn/img_convert/4ec4440492c1a366882590b30b01e1b8.png)
输出的结果为:
![10054cf7e587af4226597b3f8b8b9172.png](https://img-blog.csdnimg.cn/img_convert/10054cf7e587af4226597b3f8b8b9172.png)
很显然,不能得到a的默认值。
接下来我们使用比较特殊的NaN来尝试一下。直接上代码:
![d52a285096198e31f9ce1caacd1f4e32.png](https://img-blog.csdnimg.cn/img_convert/d52a285096198e31f9ce1caacd1f4e32.png)
输出的结果为:
![1cb8d64b8dc3ee03b9323b842c988cdf.png](https://img-blog.csdnimg.cn/img_convert/1cb8d64b8dc3ee03b9323b842c988cdf.png)
NaN很显然也会覆盖掉默认值。
至于一般的数据类型(string,number, boolean, object)等类型希望大家去尝试一下,是否能够覆盖,在这里我就不一一的描述。
优先级总结:从上面的例子中,发现undefined不能覆盖参数默认值,null和NaN都能去覆盖参数默认值,可以得出函数参数的优先级:undefined < 默认参 < 除undefined以外的实参 (NaN / null)。
如有不足,欢迎各位大神指正!
原创文章转载请注明出处:https://www.jianshu.com/p/52f26809ceb4