# call()、apply()、bind() >`call`、`apply`、`bind` 三者都是 JavaScript 對於 Function 這種特殊的 object 內建的 method ,他們與 `this` 的關係重大,簡單來講這三個內建函式可以讓我們**改變 `this` 的指向**。 ![](https://i.imgur.com/pGr2tLD.jpg =500x) <br> - `bind` 會回傳一個 `this` 被指定的 Function copy 回來。 - `call` & `apply` 則是指定 function 的 `this`,同時呼叫 Function 。 <br> ![](https://i.imgur.com/FG956lZ.png =500x) ```javascript= var person = { firstName: 'John', lastName: 'Doe', getFullName: function(){ var fullName = this.firstName + ' ' + this.lastName; return fullName; } } person.getFullName(); var logName = function(){ console.log('Logged: ' + this.getFullName()); } logName(); ``` <br/> ### `bind()` ```javascript= var person = { firstName: 'John', lastName: 'Doe', getFullName: function(){ var fullName = this.firstName + ' ' + this.lastName; return fullName; } } var logName = function(){ console.log('Logged: ' + this.getFullName()); } var logPersonName = logName.bind(person); logPersonName(); ``` - 宣告了 logPersonName 並且取用 logName 這個function JS 內建的 `bind` method,然後傳入想要 `this` 變數指向的物件 - `bind` 方法會複製logName 函式內容,將 `this` 指向我們想要綁定的物件,並且創建成一個新的函式物件。 #### 也可以簡潔寫成這樣: ```javascript= var person = { firstName: 'John', lastName: 'Doe', getFullName: function(){ var fullName = this.firstName + ' ' + this.lastName; return fullName; } } var logName = function(){ console.log('Logged: ' + this.getFullName()); }.bind(person); logName(); ``` * `bind` 的作用: 創造 function 的 copy,然後將 `this` 指向到我們指定的物件。 * 當我們使用 `bind()` 的時候,**他並不會執行呼叫的函式,而是會創建一個新的函式**。 <br /> ### `call()` ```javascript= var person = { firstName: 'John', lastName: 'Doe', getFullName: function(){ var fullName = this.firstName + ' ' + this.lastName; return fullName; } } var logName = function(lang1, lang2){ console.log('Logged: ' + this.getFullName()); console.log('Argument: ' + lang1 + ' ' +lang2); } var logPersonName = logName.bind(person); logPersonName('es','en'); logName.call(person,'en','es'); ``` `call` 也可以讓我們決定 `this` 要指向哪個物件、也可以傳入參數。 `call` 主要有兩種參數: * 第一個參數:傳入的物件會被指定為目標函式中的 `this` * 第二以後的參數:會作為參數傳進目標函式中(如果目標函式中不需要參數則不要傳入即可) 與 `bind` 方法不同的地方是,**`call` 方法並不是創造函式的拷貝並等待呼叫,而是直接執行並且改變 `this` 的指向。** <br> ### `apply()` ```javascript= var person = { firstName: 'John', lastName: 'Doe', getFullName: function(){ var fullName = this.firstName + ' ' + this.lastName; return fullName; } } var logName = function(lang1, lang2){ console.log('Logged: ' + this.getFullName()); console.log('Argument: ' + lang1 + ' ' +lang2); } var logPersonName = logName.bind(person); logPersonName('es','en'); logName.call(person,'en','es'); logName.apply(person, ['es','en']); ``` `apply` 跟 `call` 使用上幾乎雷同,只有傳入參數的方式不太一樣。 **`call` 方法允許傳入各種型別的值,但是 `apply` 方法只接受陣列作為參數,** 所以這兩個方法會根據函式的情況來使用。 <br> #### `apply()` 的應用實例 ```javascript= function greet (l1, l2, l3) { alert( `Hello, my name is ${this.name} and I know ${l1}, ${l2}, and ${l3}` ) } const user = { name: 'Tyler', age: 27, } const languages = ['JavaScript', 'Ruby', 'Python'] greet.call(user, languages[0], languages[1], languages[2]) greet.apply(user, languages) ``` ---- ### 補充:`call` 與 `apply` 的用途 : function borrowing #### function borrowing ```javascript= var person = { firstName: 'John', lastName: 'Doe', getFullName: function(){ var fullName = this.firstName + ' ' + this.lastName; return fullName; } } var person2 = { firstname: 'Jane', lastname: 'Duke' } var logPerson2 = person.getFullName.apply(person2); console.log(logPerson2); ``` <br> ### 補充: 箭頭函示不能使用這三個內建函式去綁定this **因為箭頭函式根本沒有自己的 `this`** 也因為沒有`this`,箭頭函式不能使用建構式 ---- #### 參考資料: udemy: JavaScript : UnderStanding the weird part : lecture 50 [筆記] [了解function borrowing和function currying ─ bind(), call(), apply() 的應用 ](https://pjchender.blogspot.com/2016/06/function-borrowingfunction-currying.html) [Understanding the "this" keyword, call, apply, and bind in JavaScript ](https://ui.dev/this-keyword-call-apply-bind-javascript/)