函数的扩展

这篇文章主要介绍了函数的扩展,函数的扩展只要有三个方面:函数

1 参数的默认值优化

2 箭头函数this

3 关于尾调用的优化prototype

参数的默认值(会造成一个单独的做用域)

能够在直接定义函数的时候,定义好参数若是没传或者传错 undefined。rest

//解构的基本用法
//用法1:
function log(x, y = 'World') {
    console.log(x, y);
}
​
log('Hello');
//Hello World
​
log('Hello', 'China');
/* Hello China */
​
log('Hello', '');
/* Hello */
​
参数的默认值只有在没传时才会生效。
//用法2:
function week({ x, y = 5 }) {
    console.log(x, y);
}
​
week({});
/* undefined 5 */
​
week({x: 1});
/* 1 5 */
​
week({x: 1, y: 2});
/* 1 2 */
​
week();
/* TypeError: Cannot read property 'x' of undefined */
​
//用法3:
function week({x, y = 5} = {}) {
    console.log(x, y);
}
​
week();
/* undefined 5 */

解构和参数的默认值须要注意的点:code

  • 参数的变量已经默认声明,不能用let或const再次声明对象

    function week(x = 5) {
        let x = 1;
        const x = 2;
    }
    /* SyntaxError: Identifier 'x' has already been declared */
  • 函数不能有同名参数,由于参数的变量已经默认声明因此不能再次声明递归

    function week(x, x, y = 1) {
        /* ... */
    }
    /* SyntaxError: Duplicate parameter name not allowed in this context */
  • 参数默认值是惰性求值token

    当咱们真正运算走这个函数的时候,它才会去处理默认的参数作用域

    let x = 99;
    function week(p = x + 1) {
        console.log(p);
    }
    ​
    week();
    /* 100 */
    ​
    x = 100;
    week();
    /* 101 */
  • 参数默认值通常用于尾部,好比一个函数

  • length属性,也就是函数的name和let,返回没有指定默认值的参数个数

    (function (a) {}).length;
    //1
    ​
    (function (a = 5) {}).length;
    //0
    ​
    (function (a, b, c = 5) {}).length;
    //2
    ​
    (function (a = 0, b, c) {}).length;
    //0
    ​
    (function (a, b = 1, c) {}).length;
    //1
    ​
    (function(...args) {}).length;
    //0
  • 设置了参数的默认值,参数会造成一个单独的做用域

    var x = 1;
    function f(x, y = x) {
        console.log(y);
    }
    ​
    f(2);
    //2
    ​
    let x = 1;
    function f(y = x) {
        let x = 2;
        console.log(y);
    }
    ​
    f();
    //1

2:rest参数,只能有一个参数,部分场景能够替代argument、相似于argument

好比一个函数的argument咱们知道这是函数的参数,argument其实是官方不推荐的一种用法。

function add(...values) {
let sum = 0;
​
for (var val of values) {
    sum += val;
}
​
return sum;
}
​
add(2, 5, 3);
/* 10 */
​
function sortNumbers() {
    return Array.prototype.slice.call(arguments).sort();
}
​
const sortNumbers = (...numbers) => numbers.sort();

3:严格模式,在严格模式下,使用了默认值、解构赋值或者扩展不能使用严格模式。

4:name 返回函数名

function week() {}week.name;// "week" *

var f = function () {};f.name // ""// ES6f.name // "f"

5:箭头函数

箭头函数主要的两点是:第一点它的this指向是在它当时定义所在的做用域,第二个是它没有一个做用域的提高。

// 单个参数 
var f = v => v;
var f = function (v) {
    return v;
};
​
// 多个参数 
var sum = (num1, num2) => num1 + num2;
var sum = function(num1, num2) {
    return num1 + num2;
};
​
// return,有两种场景,箭头函数里面直接写return或者不写的话箭头函数就会默认把这个结果当成一个return。
   也就是说当咱们返回一个对象时,没有return语句的时候咱们须要再对象外面再包一个括号
var sum = (num1, num2) => { return num1 + num2; }
​
// 1 返回对象
let getTempItem = id => { id: id, name: "Temp" };
// 2 Unexpected token :
let getTempItem = id => ({ id: id, name: "Temp" });
​
// 结合解构
const full = ({ first, last }) => first + ' ' + last;
​
// rest
const numbers = (...nums) => nums;
numbers(1, 2, 3, 4, 5);
// [1,2,3,4,5]

箭头函数使用的注意点:

  • 函数体内的this对象指向定义时所在的对象而不是使用时所在的对象

    function week() {
        setTimeout(() => {
            console.log('id:', this.id);
        }, 100);
    }
    //定义全局id(使用时的所在id)
    var id = 21;
    //调用,改变了this的值
    week.call({ id: 42 });
    // 42
    ​
    function week() {
        return () => {
            return () => {
                return () => {
                    console.log('id:', this.id);
                };
            };
        };
    }
    //定义时的id=1,决定了它的做用域,所以下面的t1,t2,t3的输出结果均为1
    var f = week.call({id: 1});
    ​
    var t1 = f.call({id: 2})()();
    var t2 = f().call({id: 3})();
    var t3 = f()().call({id: 4});
    // 1 
    ​
    // 对象不构成做用域 
    const cat = {
        lives: 9,
        jumps: () => {
            this.lives--;
        }
    }
  • 不能够看成构造函数,由于定义的时候是全局的

  • 不可使用argument对象,这是一个规定,须要使用rest来代替

  • 不可使用yield命令

6:尾调用

通常用于严格模式,也就是说在严格模式下面,ES6作了一个尾调用的优化;可是在非严格模式下虽然也可使用尾调用,可是没有优化。

尾调用基本概念:最后一步是调用另外一个函数,不适用于外部变量时只保留内层函数的调用帧(外部的变量不该该保存在return这个函数里面,也就是返回的return并不使用这个做用域)。

function f(x){
    return g(x);
}

7:尾递归(会有一个调用栈的堆积)

function factorial(n) {
    if (n === 1) return 1;
    return n * factorial(n - 1);
}
​
factorial(5);
​
// 尾递归
function factorial(n, total) {
    if (n === 1) return total;
    return factorial(n - 1, n * total);
}
​
factorial(5, 1)

8:函数参数的尾逗号,方便代码版本管理

func(
    'week',
    'month',
);
相关文章
相关标签/搜索