# call()、apply()、bind()
>`call`、`apply`、`bind` 三者都是 JavaScript 對於 Function 這種特殊的 object 內建的 method ,他們與 `this` 的關係重大,簡單來講這三個內建函式可以讓我們**改變 `this` 的指向**。

<br>
- `bind` 會回傳一個 `this` 被指定的 Function copy 回來。
- `call` & `apply` 則是指定 function 的 `this`,同時呼叫 Function 。
<br>

```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/)