前言
Function有三種用法,除了一般呼叫方式外,還可以使用Function.prototype.call()
或Function.prototype.apply()
方法。此外,Function還有一個很常見,偶爾會與後兩個用法混淆的方法–Function.prototype.bind()
。沒錯,這節就是要來說說Function.prototype.bind()
和另外兩者的差異,以及常見用法和你可能不知道的Function.prototype.bind()
。
<Fn>.call()
/<Fn>.apply()
和 <Fn>.bind()
的差異
由於過去其實我是寫過bind()
的相關內容的。所以我個人並不曾將三者搞混,蠻能區分用法上的不同的。不過在偶然幾次討論程式碼應該如何寫的過程中,發現偶爾會有人弄不清楚何時應該使用bind()
?何時使用其他兩者?
回頭看我過去所寫的,也蜻蜓點水的點到過call()
和apply()
。它們三者的參數形式確實有些像,特別是bind()
和call()
都接受一個thisArg
參數和多個參數展開。
所以Function.prototype.bind()
有甚麼不同之處嗎?
Function.prototype.call()
和Function.prototype.apply()
與一般函式呼叫寫在同一節裡,他們三著共同點是「會真的執行函示內容」。與他們不同的是Function.prototype.bind()
並不會真的執行函式,它會返回一個新的函式。
function helloWorld() {
console.log(`Hello World`)
}
helloWorld(); // 會印出 Hello World
helloWorld.call(); // 會印出 Hello World
helloWorld.apply(); // 會印出 Hello World
helloWorld.bind(); // 不會印出 Hello World。返回一個函式物件
新的函式物件與原本的可能沒有什麼差異:
var newFn1 = helloWorld.bind();
newFn1(); // 會印出 Hello World
雖然上面程式碼很像是直接賦值給變數,但還是有些差異。
var newFn2 = helloWorld;
newFn2 === helloWorld; // true。直接賦值的話是同一個函式物件
newFn1 === helloWorld; // false。使用bind()會產生一個新的函式物件,儘管它們用起來可能很像,但依然不同
直接賦值的話是同一個函式物件;相對來說,使用bind()
會產生一個新的函式物件。儘管它們用起來可能很像,但依然不同。
常見用法
在JavaScript裡面this
是一個特別的存在。它經常會有隱含綁定和隱含遺失的狀況。