函數的擴展

這篇文章主要介紹了函數的擴展,函數的擴展只要有三個方面:函數

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',
);
相關文章
相關標籤/搜索