JavaScript學習筆記(高階函數二)

JavaScript學習筆記(高階函數二)

箭頭函數

ES6標準新增了一種新的函數:Arrow Function(箭頭函數)。
例如:

function(x){
	return x * x;
}

用箭頭函數來表示:

x => x * x

箭頭函數相當於匿名函數,並且簡化了函數定義。箭頭函數有兩種格式

x => {
    if (x > 0) {
        return x * x;
    }
    else {
        return - x * x;
    }
}

如果參數不是一個,就需要用括號()括起來:

//兩個參數
(x,y) => x * x + y * y

//無參
(s) => 3.14

//可變參
(x,y,...rest) => {
    var i,sum = x+ y;
    for(i = 0;i<rest.length;i++){
        sum += rest[i];
    }
    return sum;
}

如果要返回一個對象,就要注意,如果是單表達式,這麼寫的話會報錯:

//SyntaxError:
x => {foo:x}

因爲和函數體的{ … }有語法衝突,所以要改爲:

//正常
x = > ({foo:x)

this
箭頭函數 看上去是匿名函數的一種簡寫,但實際上,箭頭函數和匿名函數有個明顯的區別:箭頭函數內部的this是詞法作用域,由上下方文確定。

var boj = {
    birth:1990,
    getAge:function (){
        var b = this.birth;//1990
        var fn = function () {  
            return new Date.getFullYear() - this.birth;//
        };
        // var fn = () => new Date().getFullYear() - this.birth; // this指向obj對象
        return fn();
    }
};

console.log(boj.getAge());

會報錯誤:
在這裏插入圖片描述
修改爲:

var boj = {
    birth:1990,
    getAge:function (){
        var b = this.birth;//1990
        
        var fn = () => new Date().getFullYear() - this.birth; // this指向obj對象
        return fn();
    }
};

console.log(boj.getAge());

在這裏插入圖片描述
如果使用了箭頭函數 ,以前的那種hack寫法:
var that = this;
就不需要 了。

generator

generator(生成器)是ES6標準引入的新的數據類型,一個generator看上去像一個函數,可以返回多次。
函數的定義

functoin foo(x){
	return x + x;
}
var r = foo(1);//調用foo函數

函數在執行過程中,如果沒有遇到return語句(函數末尾如果沒有return ,就量隱含的return undefined;),控制權無法交回被調用的代碼。

function* foo(x){
	yield x + 1;
	yield x + 2;
	return x + 3;
}

generator和函數不同的是,generator由function* 定義(注意多出的*),並且,除了return 語句,還可以用yield返回多次。
我們以一個著名的斐波那契數列爲例,它由0,1開頭:

0 1 1 2 3 5 8 13 21 34 ...
function* flb(max) {  
    var 
        t,
        a = 0,
        b = 1,
        n = 0;
    while(n < max){
        yield a;
        [a,b] = [b,a + b];
        n ++;
    }
    return ;
}
// fib(5)僅僅是創建了一個generator對象,還沒有去執行它。
console.log(flb(5));
//第一種方式:不斷地調用generator對象的next()方法
var f = flb(5);
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: false}
f.next(); // {value: undefined, done: true}
//第二種方式:使用for..of遍歷
for (const x of flb(10)) {
    console.log(x);
}

next()方法會執行generator的代碼,然後,每次遇到yield x;就返回一個對象{value:x,done:true/false},然後”暫停“。返回的value就是yiled的返回值,done表示這個generator是否已經執行結束了,如果done爲true,則value就是return 的返回值。
因爲generator可以在執行過程中多次返回,所以它看上去就像現代戰爭可以記住執行狀態的函數,利用這一點,寫一個generator就可以實現需要面向對象才能實現的功能。例如,用一個對象來保存狀態,得這麼寫:

var fib = {
    a:0,
    b:1,
    n:0,
    max:5,
    next:function () {  
        var 
            r = this.a,
            t = this.a + this.b;
        this.a = this.b;
        this.b = t;
        if(this.n < this.max){
            this.n ++;
            return r;
        }else{
            return  undefined;
        }
    }
}

generator還有另一個巨大的好處,就是把異步回調代碼變成“同步”代碼。這個好處要等到後面學了AJAX以後才能體會到。
沒有generator之前的黑暗時代,用AJAX時需要這麼寫代碼:

ajax('http://url-1', data1, function (err, result) {
    if (err) {
        return handle(err);
    }
    ajax('http://url-2', data2, function (err, result) {
        if (err) {
            return handle(err);
        }
        ajax('http://url-3', data3, function (err, result) {
            if (err) {
                return handle(err);
            }
            return success(result);
        });
    });
});

用generator來寫

try {
    r1 = yield ajax('http://url-1', data1);
    r2 = yield ajax('http://url-2', data2);
    r3 = yield ajax('http://url-3', data3);
    success(r3);
}
catch (err) {
    handle(err);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章