函数是将复用的代码块封装起来的模块,在JS中函数是对象,每个函数都是Function对象实例。

声明定义

  1. 关键字定义
  2. 对象字面量定义
  3. Function对象定义 ```javascript // 字面量定义函数 function show() { console.log(‘Hello World!’); }

// Function对象定义函数 let display = new Function(console.log(‘Hello World!’));

  1. <a name="jVA8C"></a>
  2. ### 函数表达式(匿名函数)
  3. 函数是对象所以可以通过赋值来指向到函数对象的指针,当然指针也可以传递给其他变量,注意后面要以`;`结束。
  4. ```javascript
  5. let foo = function () {
  6. console.log('foo');
  7. };
  8. let bar =foo;
  9. bar(); // foo

函数提升

函数使用关键字定义时会发生提升,使用表达式时不会提升并且报错。

  1. sum(2, 3); // 5
  2. function sum(x, y) {
  3. return x + y;
  4. }
  5. sum(2,3); // Cannot access 'sum' before initialization
  6. let sum = function (x,y){
  7. return x+y;
  8. }

函数参数

形参与实参

形参是在函数声明时设置的参数,实参指在调用函数时传递的值。

  • 形参数量大于实参时,没有传参的形参值为 undefined
  • 实参数量大于形参时,多于的实参将忽略并不会报错 ```javascript // x,y为形参 function sum(x, y) { return x + y; }

// 2,3位实参 console.log(sum(2, 3));

  1. <a name="HqCDW"></a>
  2. #### 默认参数
  3. 1. 如果函数未提供参数,那么其默认值则是 undefined。
  4. 1. 在ES5.1及以前默认参数是判断传入的参数是否为undefined来设置。
  5. 1. ES6显示定义默认参数值,且默认参数必须放在参数列表最后。
  6. ```javascript
  7. function sum(x, y) {
  8. x = (typeof x !== 'undefined') ? x : 2;
  9. y = y || 3;
  10. return x + y;
  11. }
  12. console.log(sum()); // 5
  13. // ES6
  14. function sum(x, y = 3) {
  15. return x + y;
  16. }
  17. console.log(sum(2)); // 5

arguments 对象

JS函数不在乎形参列表和实参列表是否匹配,因为传入的参数表现为一个数组,可以使用 arguments 对象来访问传入的参数。
arguments 对象是一个类数组对象(但不是 Array 的实例),因此可以使用中括号语法访问其中的元素(第一个参数是 arguments[0],第二个参数是 arguments[1])。而要确定传进来多少个参数可以访问 arguments.length 属性。

  1. function test() {
  2. console.log(arguments[0],arguments[1]);
  3. }
  4. test('第一个参数','第二个参数');

参数展开与收集

ES6新増了扩展操作符,使用它可以非常简洁地操作和组合集合数据。扩展操作符最有用场景就是函数定义中的参数列表,在这里它可以充分利用这门语言的弱类型及参数长度可变的特点。 扩展操作符既可以用于调用函数时传参,也可以用于定义函数参数。

  1. // 展开
  2. let arr = [1, 2, 3];
  3. let [a, b, c] = [...arr];
  4. console.log(a, b, c);
  5. // 收集
  6. function test(...params) {
  7. console.log(params);
  8. }
  9. test(1, 2, 3, 4, 5);

箭头函数(拉姆达表达式)

ES6新增的语法糖之一,是函数声明的简写形式,在使用递归调用、构造函数、事件处理器时不建议使用箭头函数。

  • 无参数时使用空扩号即可。
  • 只有一个参数时可以省略括号。
  • 多参数传递与普通声明函数一样使用逗号分隔。
  • 函数体为单一表达式时不需要 return 返回处理,系统会自动返回表达式计算结果。 ```javascript // 无参数 let test1 = () => { return 1 + 1; };

// 一个参数 let test2 = (x) => { return x.length; }; console.log(test(‘abc’)); // 3

// 多个参数 let test3 = (x, y) => { return x + y; };

// 返回值为单一表达式时 let test4 = (x, y) => x + y; console.log(test4(2, 3));

  1. <a name="UUUKs"></a>
  2. ### 递归调用
  3. 递归指函数内部调用自身的方式。
  4. - 主要用于数量不确定的循环操作
  5. - 要有退出时机否则会陷入死循环
  6. ```javascript
  7. // 阶乘
  8. function factorial(x) {
  9. if (x === 1) {
  10. return 1;
  11. } else {
  12. return x * factorial(x - 1);
  13. }
  14. }
  15. console.log(factorial(3));
  16. // 求和
  17. function sum(n) {
  18. if (n == 1) {
  19. return 1;
  20. } else {
  21. return sum(n - 1) + n;
  22. }
  23. }
  24. console.log(sum(100));
  25. // 斐波那契数列
  26. function fib(n) {
  27. if (n === 1 || n === 2) {
  28. return n - 1;
  29. } else {
  30. return fib(n - 1) + fib(n - 2);
  31. }
  32. }
  33. console.log(fib(10)); // 34
  34. // 爬楼梯
  35. function climbStairs(n) {
  36. if (n == 1) return 1;
  37. if (n == 2) return 2;
  38. return climbStairs(n - 1) + climbStairs(n - 2);
  39. }
  40. console.log(climbStairs(3));

回调函数

在某个时刻被其他函数调用的函数称为回调函数。此时函数作为值传递。

  1. function ask(question, yes, no) {
  2. question ? yes() : no();
  3. }
  4. let yes = () => {
  5. console.log('YES');
  6. };
  7. let no = () => {
  8. console.log('NO');
  9. };
  10. ask('Do you Agree?', yes, no);