ES6 之 函数的扩展

函数参数的默认值

    function log(x, y) {
      y = y || 'world'
      console.log(x + ' ' + y);
    }
    log('hello') // hello world
    log('hello','China') // hello China
    log('hello', '') // hello world
    /*
    * 如果 y 没有赋值,指定默认值为world // log('hello') // hello world
    * 如果 y 有赋值,指定赋值  log('hello','China') // hello China
    * 如果 y 有赋值,但是为 boolean 值 false,则该赋值就不起作用了  log('hello', '') // hello world
    * */

函数的length属性

console.log((function (a) {}).length) // 1
console.log((function (a = 1) {}).length) // 0 
console.log((function (a, b = 1, c) {}).length) //1
console.log((function (a, b , c = 2) {}).length) // 2
// 返回没有赋值形参的个数
// 如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数

箭头函数

var f = v => v;
    // 如果见箭头函数不需要参数 或者 需要对个参数,就是用圆括号代表参数部分
    var sum = (num1, num2) => num1 + num2
    // 如果箭头函数的代码块部分多余一条语句,就要使用大括号将其阔起来,
    // 并使用return语句返回

    // 如果箭头函数直接返回一个对象,必须在对象外面加上括号
    var getTempItem = id => ({ id: id, name: "Temp"})

    // 箭头函数 注意事项
    /*
    * 函数体内的this对象就是定义时所在的对象,而不是使用时所在的队形
    * 不可以当做构造函数
    * 不可以使用arguments对象
    * 不可以使用yield命令,因此箭头函数態用作Generator函数
    * 箭头函数可以让this指向固定化,这种形式非常有利于封装回调函数
    * 箭头函数可以绑定this,大大减少了显示绑定this对象的写法(call,apply,bind)*/

作用域

赋值的形参形成单独的作用域

箭头函数

《ES6标准入门》 第三版

箭头函数有几个使用注意点。
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
上面四点中,第一点尤其值得注意。this对象的指向是可变的,但是在箭头函数中,它是固定的。

箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。

箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。

绑定this

箭头函数可以绑定this对象,大大减少了显式绑定this对象的写法(call、apply、bind)。但是,箭头函数并不适用于所有场合,所以现在有一个 提案,提出了“函数绑定”(function bind)运算符,用来取代call、apply、bind调用。
函数绑定运算符是并排的两个冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对 象),绑定到右边的函数上面。

如果双冒号左边为空,右边是一个对象的方法,则等于将该方法绑定在该对象上面。

尾调用及优化

就是指某个函数的后一步是调用另一个函数。

函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。

如果在函数A的内部调用函数B,那 么在A的调用帧上方,还会形成一个B的调用帧。

等到B运行结束,将结果返回到A,B的调用帧才会消失。如果函数B内部还调用函数C,那就还有一 个C的调用帧,

以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。


尾调用由于是函数的后一步操作,所以不需要保留外层函数的调用帧,因为调用位置、内部变量等信息都不会再用到了,只要直接用内层函数的调用 帧,取代外层函数的调用帧就可以了。

只保留内层函数的调用帧。如果所有函数都是尾调用,那么完全可以做到每次执行时,调用帧只有 一项,这将大大节省内存。这就是“尾调用优化”的意义。
注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”。

尾递归及优化

函数调用自身,称为递归。如果尾调用自身,就称为尾递归。

递归非常耗费内存,因为需要同时保存成千上百个调用帧,很容易发生“栈溢出”错误(stack overflow)。但对于尾递归来说,由于只存在一个调用帧, 所以永远不会发生“栈溢出”错误。

ES6 中只要使用尾递归,就不会发生栈溢出,相对节省内存。

猜你喜欢

转载自www.cnblogs.com/houfee/p/10090850.html