- 原文地址:Javascript: call(), apply() and bind()
- 原文做者:Omer Goldberg
- 譯文出自:掘金翻譯計劃
- 本文永久連接:github.com/xitu/gold-m…
- 譯者:YueYong
- 校對者:Guangping, sun
咱們瞭解到,在面向對象的 JS 中,一切都是對象。由於一切都是對象,咱們開始明白咱們能夠爲函數設置並訪問額外的屬性。javascript
經過原型給函數設置屬性而且添加其餘方法很是棒...可是咱們如何訪問它們?!???!前端
當他說 「myself」 時,他的確意味着 ‘this’java
咱們介紹過 this
關鍵字。咱們瞭解到每一個函數都會自動獲取此屬性。因此這時,若是咱們建立一個有關咱們函數執行上下文的抽象模型(我不是惟一一個這麼作的人!...對嗎?!?!),它看起來就會像這樣:android
咱們花了一些時間來熟悉 this
關鍵字,可是一旦咱們這樣作了,咱們就開始意識到它是多麼有用了。this
在函數內部使用,而且老是引用單個對象 — 這個對象會在使用 「this」 的地方調用函數。ios
可是生活確定都不是完美的。有時候咱們會失去 this
的引用。當這種狀況發生時,咱們最終使用了使人困惑的解決方法去保存咱們對於 this
的引用。讓咱們經過 localSorage 練習來看看這個方法吧:git
第 31 行 :(github
那爲何我須要保存 this
引用呢?由於在 deleteBtn.addEventListener 中,this
指向了 deleteBtn 對象。這並不太好。有更好的解決方案嗎?編程
到目前爲止,咱們已將函數視爲由名稱(可選,也能夠是匿名函數)及其在調用時執行的代碼所組成的對象。但這並非所有真相。做爲一個 熱愛真理的人,我必須讓你知道一個函數實際上看起來更接近下面的圖像:後端
這是什麼???????別擔憂!如今,我將經過示例介紹每一個函數中出現的這 3 種相似方法。真是很讓人興奮呢!數組
官方文檔說: 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()
方法:
pokemonName
的實例,並將 pokemon
綁定到 this
變量。 重要的是要理解它複製了 pokemonName 函數。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() 方法的官方文檔說:call()
方法調用一個給定 this
值的函數,並單獨提供參數。
這意味着,咱們能夠調用任何函數,並明確指定 this
應該在調用函數中引用的內容。真的相似於 bind()
方法!這絕對可讓咱們免於編寫 hacky 代碼(即便咱們仍然是 hackerzzz)。
bind()
和 call()
之間的主要區別在於 call()
方法:
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 連接。
掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。