[譯] Javascript: call()、apply() 和 bind()

回顧一下 「this」

咱們瞭解到,在面向對象的 JS 中,一切都是對象。由於一切都是對象,咱們開始明白咱們能夠爲函數設置並訪問額外的屬性。javascript

經過原型給函數設置屬性而且添加其餘方法很是棒...可是咱們如何訪問它們?!???!前端

當他說 「myself」 時,他的確意味着 ‘this’java

咱們介紹過 this 關鍵字。咱們瞭解到每一個函數都會自動獲取此屬性。因此這時,若是咱們建立一個有關咱們函數執行上下文的抽象模型(我不是惟一一個這麼作的人!...對嗎?!?!),它看起來就會像這樣:android

咱們花了一些時間來熟悉 this 關鍵字,可是一旦咱們這樣作了,咱們就開始意識到它是多麼有用了。this 在函數內部使用,而且老是引用單個對象 — 這個對象會在使用 「this」 的地方調用函數ios

可是生活確定都不是完美的。有時候咱們會失去 this 的引用。當這種狀況發生時,咱們最終使用了使人困惑的解決方法去保存咱們對於 this 的引用。讓咱們經過 localSorage 練習來看看這個方法吧:git

第 31 行 :(github

那爲何我須要保存 this 引用呢?由於在 deleteBtn.addEventListener 中,this 指向了 deleteBtn 對象。這並不太好。有更好的解決方案嗎?編程


call()、apply() 和 bind() — 一個新的但願

到目前爲止,咱們已將函數視爲由名稱(可選,也能夠是匿名函數)及其在調用時執行的代碼所組成的對象。但這並非所有真相。做爲一個 熱愛真理的人,我必須讓你知道一個函數實際上看起來更接近下面的圖像:後端

這是什麼???????別擔憂!如今,我將經過示例介紹每一個函數中出現的這 3 種相似方法。真是很讓人興奮呢!數組

bind()

官方文檔說: bind() 方法建立一個新函數,在調用時,將其 this 關鍵字設置爲所需的值。(它實際上談論了更多的東西,但咱們將把它留到下一次講)

這很是強大。它讓咱們在調用函數時明肯定義 this 的值。咱們來看看 cooooode:

var pokemon = {
    firstname: 'Pika',
    lastname: 'Chu ',
    getPokeName: function() {
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
    }
};

var pokemonName = function() {
    console.log(this.getPokeName() + 'I choose you!');
};

var logPokemon = pokemonName.bind(pokemon); // creates new object and binds pokemon. 'this' of pokemon === pokemon now

logPokemon(); // 'Pika Chu I choose you!'
複製代碼

在第 14 行使用了 bind()方法

咱們來逐個分析。 當咱們使用了 bind() 方法:

  1. JS 引擎建立了一個新的 pokemonName 的實例,並將 pokemon 綁定到 this 變量。 重要的是要理解它複製了 pokemonName 函數。
  2. 在建立了 pokemonName 函數的副本以後,它能夠調用 logPokemon() 方法,儘管它最初不在pokemon 對象上。它如今將識別其屬性(Pika 和 Chu)及其方法。

很酷的是,在咱們 bind() 一個值後,咱們能夠像使用任何其餘正常函數同樣使用該函數。咱們甚至能夠更新函數來接受參數,並像這樣傳遞它們:

var pokemon = {
    firstname: 'Pika',
    lastname: 'Chu ',
    getPokeName: function() {
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
    }
};

var pokemonName = function(snack, hobby) {
    console.log(this.getPokeName() + 'I choose you!');
    console.log(this.getPokeName() + ' loves ' + snack + ' and ' + hobby);
};

var logPokemon = pokemonName.bind(pokemon); // creates new object and binds pokemon. 'this' of pokemon === pokemon now

logPokemon('sushi', 'algorithms'); // Pika Chu  loves sushi and algorithms

複製代碼

call(), apply()

call() 方法的官方文檔說:call() 方法調用一個給定 this 值的函數,並單獨提供參數。

這意味着,咱們能夠調用任何函數,並明確指定 this 應該在調用函數中引用的內容。真的相似於 bind() 方法!這絕對可讓咱們免於編寫 hacky 代碼(即便咱們仍然是 hackerzzz)。

bind()call() 之間的主要區別在於 call() 方法:

  1. 支持接受其餘參數
  2. 當它被調用的時候,當即執行函數。
  3. call() 方法不會複製正在調用它的函數。

call()apply() 使用於徹底相同的目的。 它們工做方式之間的惟一區別call() 指望全部參數都單獨傳遞,而 apply() 須要全部參數的數組。例如:

var pokemon = {
    firstname: 'Pika',
    lastname: 'Chu ',
    getPokeName: function() {
        var fullname = this.firstname + ' ' + this.lastname;
        return fullname;
    }
};

var pokemonName = function(snack, hobby) {
    console.log(this.getPokeName() + ' loves ' + snack + ' and ' + hobby);
};

pokemonName.call(pokemon,'sushi', 'algorithms'); // Pika Chu  loves sushi and algorithms
pokemonName.apply(pokemon,['sushi', 'algorithms']); // Pika Chu  loves sushi and algorithms
複製代碼

注意,apply 接受數組,call 接受每一個單獨的參數。

這些存在於每個 JS 函數的內置方法都很是有用。即便你最終沒有在平常編程中使用它們,你仍然會在閱讀其餘人的代碼時常常遇到它們。

若是您有任何疑問,請一如既往地經過 Instagram 與咱們聯繫。❤

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索