![JS全书:JavaScript Web前端开发指南](https://wfqqreader-1252317822.image.myqcloud.com/cover/366/32858366/b_32858366.jpg)
4.3 参数
函数可以使用参数来传递数据,也可以不使用参数。调用函数时,传递给函数的值被称为“函数的实参”(入参),对应位置的函数参数名为“形参”。
例如:
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P96_45739.jpg?sign=1739288569-zC4X2jtRIfnQYbpnIGCPP3GTXOzjLiez-0-737656ab900d573e4e82ec9a7c3c8ada)
在上面的示例中,a和b为形参,1和2为实参。
形参与实参的位置是一一对应的,如果实参的个数小于形参的个数,剩余的形参默认值为undefined,示例如下。
foo(1);
// > 1 // > undefined
4.3.1 按值传递
参数是按值传递的,如果参数是一个包含原始值(数字、字符串、布尔值)的变量,则就算函数在内部改变了参数的值,该参数在函数外的值也不会改变,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P97_45744.jpg?sign=1739288569-JK66ivpsw2qh5Zz1REosZczwnC5Vswb9-0-ffa68a5a3afe0fc168f53af2c6f8727a)
上述代码中,我们在函数内部改变了传入的a的值,但函数执行完毕后,变量a的值没有发生任何变化,这表示传入函数内部的仅仅是变量a的值,而不是变量a。
如果参数是一个引用类型的数据,则形参和实参指向同一个对象,假如在函数内部改变了形参的值,实参指向的对象的值也会改变,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P97_45746.jpg?sign=1739288569-iuKhtTlgKJwoRI947N02NEM9Lm9EDZoC-0-a962ac08e26f7291b549c3c9900c611e)
但如果改变的是形参的地址,则实参与形参地址不同,不再指向同一个对象,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P97_45748.jpg?sign=1739288569-Hf1dz8rE5C3hhMaNeFzTEvkxCL2fEAkS-0-d1d58b747963c189f197908221533e40)
上述代码中,在函数内部,我们直接为参数obj赋值了一个新的地址,然后为函数内部的变量obj添加值为"0"的name属性,在执行函数foo时,打印出参数obj的值{name: "0"},然后打印变量obj的值,两者的值不一致。这也就是说,在修改了形参的地址后,实参中所存储的地址并没有发生变化,从而证明了引用类型的数据时传递的是地址值,而不是引用值,否则在修改形参的地址后,实参的地址也会发生改变。
4.3.2 arguments
我们可以在定义函数时为函数指定参数,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P98_45751.jpg?sign=1739288569-pNJeOEQlAyjDL1kdBuvOw5y3LLgxDmjC-0-474899dcf3f9fbaed02d0f14b54c8f81)
但有时,我们无法确定需要传递的参数的个数,这时就需要有一种方式获取所有参数,JavaScript提供了一个类数组的对象arguments,以获取传递给函数的参数。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P98_45753.jpg?sign=1739288569-o0jistanIV9P8ps41Leo1rHr78fHhJwY-0-5db8ae3a2f03efd3d370fc6431aec4b7)
看起来arguments对象是一个数组,它拥有length属性,而且可以通过下标来访问,但实际上,arguments对象除了这两个特性外,并没有数组的实例方法,如果在其上调用数组的实例方法,程序将会出错,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P98_45755.jpg?sign=1739288569-hrkdbW66e71PCCKeErUqS3RvtaSA4ah0-0-ef0fdf5e90b5d8b25137275474064372)
arguments可以被转化为一个真正的数组,示例如下。
// 两种方式
Array.prototype.slice.call(arguments);
Array.from(arguments);
4.3.3 Rest参数(剩余参数)
除了Array.from,Rest参数也可以将参数转化为数组,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P99_45757.jpg?sign=1739288569-hrC7cSQuy4tMtYvbz5GvTsQRSm8tBHJy-0-f450677359f156482e34a0f5382a8d93)
Rest参数可以不必包含所有的实参,相比arguments,其更加自由,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P99_45759.jpg?sign=1739288569-CnDlJqcIcgkHDTcTnQtuapdqxUcQrXmq-0-ad67709c93b3b7342c6203a240e95aa8)
注意:Rest参数之后不能有其他参数。
Rest参数是一个数组,这意味着它也可以被解构,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P99_45761.jpg?sign=1739288569-ZEGhCx3Zx6LnAfYgoD8RpWDTXCZe6vJI-0-d2e61c5810efe4c5896a90c5227bb5bd)
4.3.4 箭头函数中的arguments对象
箭头函数中是不能使用arguments的,在箭头函数中,arguments将会被当作一个普通的变量,示例如下。
let foo = ()=> console.log(arguments);
foo(1); // -> Uncaught ReferenceError: arguments is not defined 如果需要使用类似 arguments 的功能,可以使用 Rest 参数来代替:
let foo = (...args)=> console.log(args);
foo(1); // > [1]
4.3.5 默认参数
ES6中加入了默认参数,以便于在定义函数时为参数指定默认值。在此之前,我们通常像下面这样为函数参数指定默认值。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P99_45765.jpg?sign=1739288569-5tGLUc62moa9ksUcf3CCctHb1pCIZqcw-0-429318b45cb96e877a0842082b4152c2)
得益于默认参数,上述代码可以简化如下。
function foo(a = 1, b = 2){ console.log(a, b); }
在上文中,我们已经指定形参的默认值为undefined,而默认参数生效的条件就是值为undefined时才生效,示例如下。
![](https://epubservercos.yuewen.com/A25E65/17640316907888206/epubprivate/OEBPS/Images/Figure-P100_45769.jpg?sign=1739288569-PFpXugJ368Gh6rWAsT9HosrzHctZuFpJ-0-12feca557266ae86611fd1fb837c8568)
练习
- 使用function定义一个函数,接收多个数字作为参数,返回第一个参数与其他参数的和的积。
- 为该函数指定默认参数值。
- 将该函数修改为箭头函数。