---
# System prepended metadata

title: call()、apply()、bind()

---

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

