爲何我不推薦爲了綁定this而使用箭頭函數

現象

在咱們平常開發當中,咱們寫一個組件,常常遇到須要傳遞一個方法給點擊事件等等,那麼咱們常常是怎麼作的呢?javascript

class Item extends Component {
    jump = () => {
        this.setState({ xxx: true });
    };
    render() {
        return (
            <div onClick={this.jump}>跳轉囉</div>
        );
    }
}

如上代碼,由於點擊回調使用了this,爲了綁定this,使用了箭頭函數。或者不使用箭頭函數了,用bind進行綁定。java

class Item extends Component {
    jump() {
        this.setState({ xxx: true });
    }
    render() {
        // 在render裏進行bind
        return (
            <div onClick={::this.jump}>跳轉囉</div>
        );
    }
}

亦或者是這樣函數

class Item extends Component {
    constructor() {
        // 在初始化就綁定
        this.jump = this.jump.bind(this);
    }
    jump() {
        this.setState({ xxx: true });
    }
    render() {
        return (
            <div onClick={this.jump}>跳轉囉</div>
        );
    }
}

是否是!是否是!我相信以上3種綁定方式起碼有90%的佔有率!!!this

這樣的綁定壞處是什麼

咱們一個一個狀況來分析。prototype

箭頭函數綁定

問題1:

咱們知道使用箭頭函數的時候,他實際上該方法是放在了實例上面,而不是prototype上面,舉個例子。code

class A {
    a = '1'
    func1() {
        
    }
    func2 = () => {};
}
const a = new A();

你們能夠試試在控制檯看一下a究竟長什麼樣子,如無心外他應該是介個樣子的。繼承

{
    a: '1',
    func2: () => {},
    __proto__: {
        func1: function() {}
    }
}

那麼咱們想一想,假設咱們在一個列表item組件上使用箭頭函數,實際上他的實例是怎麼樣的。
就是每個實例上的箭頭函數都不是在prototype公用的而是本身建立一個函數!那麼相似在商品列表種的商品item,大家如今還以爲使用箭頭函數綁定this嗎?事件

問題2

相信你們都使用過了修飾器了,那麼你們想一想,修飾器 能修飾箭頭函數嗎?
答案是不能!
修飾器的輸入是什麼ip

function boundMethod(target, key, descriptor) {
    return {
        // 新的descriptor
    };
}

其中target是實例自己,key是被修飾的key,descriptor是該屬性的描述。
咱們來看一下修飾prototype上的方法跟修飾箭頭函數有什麼不一樣。開發

const testDes = function() {
    return function(target, name, descriptor) {
        return {
            ...descriptor,
            value: function() {
                console.log('descaaaa')
                descriptor.value();
            }
        };
    };
};

class A {
    @testDes(1)
    func1() {

    }
    @testDes(1)
    func2 = () => {
        
    }
}

var a = new A();
a.func1();
a.func2();
console.log(a)

以上例子,咱們發現只有a.func1()=纔會有打印修飾的字符,修飾器是不能修飾prototype上不存在的屬性的。

問題3

你們想想,若是一個類中使用了箭頭函數,那麼這個類能夠被繼承嗎?
答案就是不能夠了。
由於箭頭函數並不聲明在prototype上,因此該方法不能在子類上被使用,致使一種奇怪的錯覺。

在render裏bind綁定

其實這個問題比較明顯,咱們都知道bind方法是返回一個新的方法,就是在每次render的時候都會建立新的函數,銷燬上一次的函數。在render觸發比較頻繁的時候,就會有很是多沒有必要的建立銷燬開銷。

在constructor裏bind綁定

這個方式其實跟箭頭函數有類似之處,就是在實例自己再次賦值一個經過bind的方法,也就是多個實例之間各自都有一個方法,而且該類prototype上的方法就冗餘了。

怎麼解決

既然以上的綁定this都或多或少有很差的地方,可是實際使用咱們常常須要綁定this,那麼怎麼綁定this纔是最好的呢?
答案就是使用修飾器進行綁定。
你們能夠看一下autobind-decorator這個庫,很是簡單,使用修飾器進行綁定,就是直接在prototype上進行更改,多個實例共享沒問題,繼承也沒毛病,該方法依舊能夠被再次修飾。完美了!

看到這篇文章的你,知道怎麼綁定this了嗎?

相關文章
相關標籤/搜索