函数是将复用的代码块封装起来的模块,在JS中函数是对象,每个函数都是Function对象实例。
声明定义
- 关键字定义
- 对象字面量定义
- Function对象定义 ```javascript // 字面量定义函数 function show() { console.log(‘Hello World!’); }
// Function对象定义函数 let display = new Function(console.log(‘Hello World!’));
<a name="jVA8C"></a>### 函数表达式(匿名函数)函数是对象所以可以通过赋值来指向到函数对象的指针,当然指针也可以传递给其他变量,注意后面要以`;`结束。```javascriptlet foo = function () {console.log('foo');};let bar =foo;bar(); // foo
函数提升
函数使用关键字定义时会发生提升,使用表达式时不会提升并且报错。
sum(2, 3); // 5function sum(x, y) {return x + y;}sum(2,3); // Cannot access 'sum' before initializationlet sum = function (x,y){return x+y;}
函数参数
形参与实参
形参是在函数声明时设置的参数,实参指在调用函数时传递的值。
- 形参数量大于实参时,没有传参的形参值为 undefined
- 实参数量大于形参时,多于的实参将忽略并不会报错 ```javascript // x,y为形参 function sum(x, y) { return x + y; }
// 2,3位实参 console.log(sum(2, 3));
<a name="HqCDW"></a>#### 默认参数1. 如果函数未提供参数,那么其默认值则是 undefined。1. 在ES5.1及以前默认参数是判断传入的参数是否为undefined来设置。1. ES6显示定义默认参数值,且默认参数必须放在参数列表最后。```javascriptfunction sum(x, y) {x = (typeof x !== 'undefined') ? x : 2;y = y || 3;return x + y;}console.log(sum()); // 5// ES6function sum(x, y = 3) {return x + y;}console.log(sum(2)); // 5
arguments 对象
JS函数不在乎形参列表和实参列表是否匹配,因为传入的参数表现为一个数组,可以使用 arguments 对象来访问传入的参数。
arguments 对象是一个类数组对象(但不是 Array 的实例),因此可以使用中括号语法访问其中的元素(第一个参数是 arguments[0],第二个参数是 arguments[1])。而要确定传进来多少个参数可以访问 arguments.length 属性。
function test() {console.log(arguments[0],arguments[1]);}test('第一个参数','第二个参数');
参数展开与收集
ES6新増了扩展操作符,使用它可以非常简洁地操作和组合集合数据。扩展操作符最有用场景就是函数定义中的参数列表,在这里它可以充分利用这门语言的弱类型及参数长度可变的特点。 扩展操作符既可以用于调用函数时传参,也可以用于定义函数参数。
// 展开let arr = [1, 2, 3];let [a, b, c] = [...arr];console.log(a, b, c);// 收集function test(...params) {console.log(params);}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));
<a name="UUUKs"></a>### 递归调用递归指函数内部调用自身的方式。- 主要用于数量不确定的循环操作- 要有退出时机否则会陷入死循环```javascript// 阶乘function factorial(x) {if (x === 1) {return 1;} else {return x * factorial(x - 1);}}console.log(factorial(3));// 求和function sum(n) {if (n == 1) {return 1;} else {return sum(n - 1) + n;}}console.log(sum(100));// 斐波那契数列function fib(n) {if (n === 1 || n === 2) {return n - 1;} else {return fib(n - 1) + fib(n - 2);}}console.log(fib(10)); // 34// 爬楼梯function climbStairs(n) {if (n == 1) return 1;if (n == 2) return 2;return climbStairs(n - 1) + climbStairs(n - 2);}console.log(climbStairs(3));
回调函数
在某个时刻被其他函数调用的函数称为回调函数。此时函数作为值传递。
function ask(question, yes, no) {question ? yes() : no();}let yes = () => {console.log('YES');};let no = () => {console.log('NO');};ask('Do you Agree?', yes, no);
