函数的扩大咱们能够从三个方面来理解与意识:
- 参数的默认值
- 箭头函数
- 对于尾调用的优化
参数的默认值
在 ES6
之前,咱们不能间接为函数的参数指定默认值,只能采纳变通的办法。而 ES6
中容许咱们间接为函数的参数设置默认值,通过等号 =
间接在小括号中给参数赋值。
示例:
function log(name, age = 18) { console.log(name, age);}console.log('xkd'); // 输入: xkdconsole.log('summer', 20); // 输入: summer 20console.log('mark', ''); // 输入: mark
如果函数带有某一个参数,则示意这个参数变量曾经默认申明,咱们不能够应用 let
或者 const
再次申明这个变量。
function xkd(a = 1) { let a = 2;}// 报错:SyntaxError: Identifier 'a' has already been declared
还须要留神的是,在应用函数默认参数时,不容许有同名参数:
function week(a, a, b = 100) { /* ... */}// 报错信息: SyntaxError: Duplicate parameter name not allowed in this context
参数默认值是惰性求值:
let a = 100;function xkd(sum = a + 1) { console.log(sum);}xkd(); // 输入:101
rest不定参数
ES6
引入 rest
参数,不定参数用来示意不确定参数个数,由 ...
加上一个具名参数标识符组成。
示例:
function add(...values) { let sum = 0; for (var val of values) { sum += val; } return sum;}console.log(add(10, 5, 7)); // 输入:22
下面代码的 add
函数是一个求和函数,利用 rest
参数,能够向该函数传入任意数目的参数。
留神 rest
参数只能放在参数组的最初,并且有且只有一个不定参数,这个参数前面不能再有其余参数,否则会报错。
function func(a, ...b, c) { // ...}// 报错:SyntaxError: Rest parameter must be last formal parameter
如果咱们要应用函数的 length
属性来获取参数的个数,是不包含 rest
参数的。
function func1(a, b){ //...}function func2(a, b, ...c){ //...}console.log(func1.length); // 输入: 2console.log(func2.length); // 输入: 2
name属性
函数的 name
属性,能够用于返回该函数的函数名。
示例:
function xkd() { console.log(xkd.name); // 输入:xkd}xkd();
也能够写成:
var xkd = function() {}console.log(xkd.name); // 输入:xkd
箭头函数
ES6
中容许应用箭头 =>
来定义函数,这样定义的函数叫做箭头函数。箭头函数次要的两点是:它的 this
指向是在它过后定义所在的区域,还一个是它没有一个作用域的晋升。
示例:
var x = function (y) { return y;}
上述函数应用箭头函数来写,能够写成:
var x = y => y;
如果箭头函数不须要参数或须要多个参数,就应用一个圆括号代表参数局部。
示例:
例如上面这个求两数之和的函数:
var sum = function(num1, num2) { return num1 + num2;}
等同于如下所示箭头函数的写法:
var sum = (num1, num2) => num1 + num2;
如果箭头函数的代码块局部多于一条语句,就要应用大括号将它们括起来,并且应用return
语句返回。
示例:
var sum = (num1, num2) => { return num1 + num2; }
因为大括号被解释为代码块,所以如果箭头函数间接返回一个对象,必须在对象里面加上括号,否则会报错。
示例:
let obj = age => ({ name: "xkd", age:age });
箭头函数能够与变量解构联合应用。
示例:
const full = ({ first, last }) => first + ' ' + last;// 等同于function full(person) { return person.first + ' ' + person.last;}
箭头函数应用时须要留神的一下几个问题:
- 函数体内的
this
对象指向的是定义时所在的对象,而不是应用时所在的对象。 - 不能够当作构造函数,也就是说不能够应用
new
命令。 - 不能够应用
arguments
对象,能够应用rest
参数代替。 - 不能够应用
yield
命令,因而箭头函数不能用作Generator
函数。
对于尾调用的优化
尾调用就是指某个函数的最初一步是调用另一个函数,不适用于内部变量时只保留内层函数的调用帧。
示例:
例如上面这个 func()
函数中的最初一步是调用函数 show()
,这就叫尾调用:
function func(x) { return show(x);}
如果在调用一个函数之后,还有其余的操作,则不属于尾调用。
留神,尾调用不肯定呈现在函数尾部,只有是最初一步操作即可,例如上面这段代码中:
function func(x) { if (x > 0) { return f1(x) } return f2(x);}
函数 f1
和 f2
都属于尾调用,因为这两个函数调用都是函数 func
的最初一步操作。
在 ES5
中,尾调用的实现是创立一个新的栈帧 stack frame
, 将其推入调用栈中示意函数调用。所以每一个未用完的栈帧都会保留在内存中,当调用栈变得过大时会造成程序问题,也就是咱们常说的栈溢出。
ES6
严格模式下,满足以下三个条件,尾调用不再创立新的 stack frame
,而是重用以后 stack frame
:
- 函数不是一个闭包。
- 在函数外部,尾调用是最初一条语句。
- 尾调用的后果作为函数值返回。
示例:
'use strict';function func(){ //优化后 return f();}
而以下几种状况不会进行优化:
- 当没有作为函数值返回,不会优化:
function func(){ f(); }
- 返回值后还须要做其余操作,也不会优化:
function func(){ return 1+f(); //返回值后还须要做其余操作};
- 函数调用不在尾部,也不会优化:
function func(){ const result = f(); return result;};
- 调用的函数是一个闭包函数,也不会优化:
function func(){ const a= 1; const f = () => a //这是一个闭包函数,函数 f 须要拜访局部变量a return f();};
更多链接:https://www.9xkd.com/