函数的扩大咱们能够从三个方面来理解与意识:

  • 参数的默认值
  • 箭头函数
  • 对于尾调用的优化

参数的默认值

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);}

函数 f1f2 都属于尾调用,因为这两个函数调用都是函数 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/