2019-02-21

函數(shù)的擴展

2、箭頭函數(shù)

使用注意點

箭頭函數(shù)有幾個注意點:
1、函數(shù)體內(nèi)的this對象,就是定義時所在的對象,而不是使用時所在的對象 (尤其要注意:this對象的指向是可變的,但是在箭頭函數(shù)中,它是固定的)
2、不可以當做構(gòu)造函數(shù),也就是說,不可以使用new命令,否則會拋出一個錯誤
3、不可以使用arguments對象,該對象在函數(shù)體內(nèi)不存在。如果要用,可以用rest參數(shù)代替
4、不可以使用yield命令,因此箭頭函數(shù)不能用作Generator函數(shù)

function foo(){
    setTimeout(()=>{
        console.log('id:',this.id);
    },100);
}

var id = 21;
foo.call({id:42});  /id: 42

如果是普通函數(shù),執(zhí)行時this應該指向全局對象window,這時應該輸出21
但是箭頭函數(shù)導致this總是指向函數(shù)定義生效時所在的對象(本例是{id:42})

箭頭函數(shù)可以讓setTimeout里面的this綁定定義時所在的作用域,而不是指向運行時所在的作用域:

function Timer(){
    this.s1=0;
    this.s2=0;
    //箭頭函數(shù)
    setInterval(()=>this.s1++,1000);
    //普通函數(shù)
    setInterval(function(){
        this.s2++;
    },1000);
}
var timer=new Timer();

setTimeout(()=>console.log('s1',timer.s1),3100);
setTimeout(()=>console.log('s2',timer.s2),3100);
//s1:3  s1使用的是箭頭函數(shù),this綁定定義時所在的作用域(即Timer函數(shù))
//s2:0 s2使用的是普通函數(shù),this指向運行時所在的作用域(即全局對象
//所以3100毫秒之后,thimer.s1被更新了3次,而timer.s2一次都沒更新。
)

箭頭函數(shù)可以讓this指向固定化,這種特性很有利于封裝回調(diào)函數(shù)。
下面的這個例子DOM事件的回調(diào)函數(shù)封裝在一個對象里面

var handler={
    id:'123456',
    init:function(){
        document.addEventListener('click',
        event=> this.doSomething(event.type),false);
    },

    doSomething:function(type){
        console.log('Handling' + type + 'for' + this.id);
    }
};

上面代碼的init方法中,使用了箭頭函數(shù),這導致了這個箭頭函數(shù)里面的this,總是指向handler對象。否則回調(diào)函數(shù)執(zhí)行時,this.doSomething這一行會報錯,因為此時this指向document對象

this指向的固定化,并不是因為箭頭函數(shù)內(nèi)部又綁定this的機制,實際原因是函數(shù)根本沒有自己的this,導致內(nèi)部的this就是外層代碼塊的this。正式因為它沒有this,所以也就不能用作構(gòu)造函數(shù)。

所以,箭頭函數(shù)轉(zhuǎn)換成ES5的代碼如下:

//ES6
function foo(){
    setTimeout(()=>{
        console.log('id:' , this.id);
    },100);
}

//ES5
function foo(){
    var _this=this;
    setTimeout(function(){
        console.log('id:',_this.id);
    },100);
}
//代碼中轉(zhuǎn)換后的ES5版本清楚的說明了,箭頭函數(shù)里面根本沒有自己的this,而是引用外層的this
function foo(){
    return () =>{
        return () =>{
            return () =>{
                console.log('id',this.id);
            }
        }
    }
}

var f=foo.call({id:1});

var t1 = f.call({id:2})()(); //id:1
var t2 = f().call({id:3})(); //id:1
var t3 = f()().call({id:4}); //id:1
//上面代碼中只有一個函數(shù)foo的this,因為所有的內(nèi)層函數(shù)都是箭頭函數(shù),都沒有自己的this,它們的this其實都是最外層foo函數(shù)的this,所以輸出的結(jié)果都是相同的。

箭頭函數(shù)沒有自己的this,所以也就不能用call()、apply()、bind()這些方法去改變this的指向

不適用場合

由于箭頭函數(shù)使得this從“動態(tài)”變成“靜態(tài)”,所以以下兩種場合不應該使用箭頭函數(shù):

第一種場合:是定義函數(shù)的方法,且該方法內(nèi)部包含this

const cat = {
    lives:9,
    jumps:() => {
        this.lives--;
    }
}//錯誤
//調(diào)用cat.jumps()方法時,如果是普通函數(shù),該方法內(nèi)部的this指向cat
//如果像上面的箭頭函數(shù),使得this指向全局對象,會得不到預期結(jié)果

第二個場合是需要動態(tài)this的時候,也不應該使用箭頭函數(shù)

var button = document.getElementById('press');
button.addEventListener('click',() =>{
    this.classList.toggle('on');
})//報錯
//因為button的監(jiān)聽函數(shù)是一個箭頭函數(shù),導致里面的this就是全局對象。
//如果改成普通函數(shù),this就會動態(tài)指向被點擊的按鈕對象

另外,如果函數(shù)體很復雜,有許多行?;蛘吆瘮?shù)內(nèi)部有大量的讀寫操作,不單純是為了計算值,這時也不應該使用箭頭函數(shù),而是使用普通函數(shù),這樣可以提高代碼可讀性

嵌套的箭頭函數(shù)

箭頭函數(shù)內(nèi)部還可以再使用箭頭函數(shù)

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • Swift1> Swift和OC的區(qū)別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,694評論 1 32
  • 函數(shù)參數(shù)的默認值 基本用法 在ES6之前,不能直接為函數(shù)的參數(shù)指定默認值,只能采用變通的方法。 上面代碼檢查函數(shù)l...
    呼呼哥閱讀 3,718評論 0 1
  • 函數(shù)參數(shù)的默認值 基本用法 在ES6之前,不能直接為函數(shù)的參數(shù)指定默認值,只能采用變通的方法。 上面代碼檢查函數(shù)l...
    陳老板_閱讀 520評論 0 1
  • 鳥,又叫鳥兒,是飛禽的總稱。有人考證,鳥類起源于恐龍。鳥會飛,也會鳴唱。“關(guān)關(guān)雎鳩,在河之洲。窈窕淑女,君子好...
    黃葉村人閱讀 936評論 2 1
  • 垂釣碧溪,石邊錦繡草。暮晚孤舟緩緩行,良辰美景如此?紅霞云上羞澀,千變不知何年。閑來雅亭悠坐,細看芙萍嬌開。
    雪雨琦兒閱讀 405評論 1 19

友情鏈接更多精彩內(nèi)容