原文地址:https://dev.to/bhagatparwinder/truly-understand-bind-call-apply-21da
Bind
JavaScript 中的 this 扮演者重要的角色,在 JavaScript 中它是依據(jù)函數(shù)是怎么被調(diào)用的而不是它在哪聲明的(箭頭函數(shù)則表現(xiàn)為相反)。
我們舉一個(gè)例子來示范一下 this 是如何工作的:
const sayGreeting = { name: “Parwinder”, hello: function() { return `Hello, ${this.name}`; }}console.log(sayGreeting.hello()); // Hello, Parwinder
hello 方法可以獲取 sayGreeting 上的 name 屬性,當(dāng)我用 sayGreeting 調(diào)用它時(shí),它是運(yùn)行在 sayGreeting 對(duì)象上下文中的。
相反如果我這樣做:
const sayGreeting = { name: “Parwinder”, hello: function() { return `Hello, ${this.name}`; }}const hello = sayGreeting.hello;console.log(hello === sayGreeting.hello); // trueconsole.log(hello()); // Hello, undefined
盡管 hello 變量與 sayGreeting 對(duì)象上的 hello 方法相等,但它的執(zhí)行上下文并不是在 sayGreeting 中,而是在 window 或全局狀態(tài)中。
bind 方法允許我們綁定上下文,它返回一個(gè)新的方法且上下文綁定為我們傳遞給 bind 函數(shù)的內(nèi)容。
const sayGreeting = { name: “Parwinder”, hello: function() { return `Hello, ${this.name}`; }}const hello = sayGreeting.hello.bind(sayGreeting);console.log(hello()); // Hello, Parwinder
實(shí)際業(yè)務(wù)中哪里需要使用 bind?
上面的所有例子,數(shù)據(jù)的獲取和方法的調(diào)用都在一個(gè)對(duì)象上 bind 的作用并不明顯??捎袝r(shí)候當(dāng)你需要向一個(gè)對(duì)象借一個(gè)方法但運(yùn)行上下文需要在另一個(gè)對(duì)象中時(shí),你就需要使用 bind。
const sayGreeting = { name: “Parwinder”, hello: function () { return `Hello, ${this.name}`; }}const nameObject = { name: “Lauren”}const hello = sayGreeting.hello.bind(nameObject);console.log(hello()); // Hello, Lauren
sayGreeting 對(duì)象上有 hello 方法,所以在 nameObject 對(duì)象上就沒有必要再寫一個(gè)相同的方法。我可以向 sayGreeting 對(duì)象借用它然后運(yùn)行在 nameObject 上下文中。
Call
call 和 apply 與 bind 是有區(qū)別的,bind 返回一個(gè)新的方法而 call 和 apply 則立即調(diào)用執(zhí)行方法。call 把 this 作為第一個(gè)參數(shù),其他參數(shù)需要一個(gè)個(gè)的傳遞。它們都會(huì)傳遞到我們調(diào)用的函數(shù)中:
const sayGreeting = { name: “Parwinder”, hello: function () { return `Hello, ${this.name}`; }}console.log(sayGreeting.hello.call(sayGreeting)); // Hello, Parwinder
帶有其它參數(shù):
const sayGreeting = { name: “Parwinder”, hello: function (trait, color) { return `Hello, ${this.name}. I see you ${trait} ${color}. It is my favorite too!`; }}console.log(sayGreeting.hello.call(sayGreeting, “like”, “red”));// Hello, Parwinder. I see you like red. It is my favorite too!
Apply
盡管 apply 和 call 類似都是直接執(zhí)行函數(shù),但它接受的是一個(gè)數(shù)組作為第二個(gè)參數(shù)而不是逗號(hào)分隔的值。
const sayGreeting = { name: “Parwinder”, hello: function () { return `Hello, ${this.name}`; }}console.log(sayGreeting.hello.apply(sayGreeting)); // Hello, Parwinder
當(dāng)沒有其余參數(shù)時(shí) apply 和 call 沒有區(qū)別,但是當(dāng)我們有其余參數(shù)時(shí),使用方法就有點(diǎn)區(qū)別:
const sayGreeting = { name: “Parwinder”, hello: function (trait, color) { return `Hello, ${this.name}. I see you ${trait} ${color}. It is my favorite too!`; }}console.log(sayGreeting.hello.apply(sayGreeting, [“like”, “red”]));// Hello, Parwinder. I see you like red. It is my favorite too!
apply 使得傳遞多個(gè)參數(shù)變得更容易些,但是現(xiàn)在 ES6 中使用擴(kuò)展運(yùn)算符傳遞多個(gè)參數(shù)也很容易了。