Web/04-JavaScript基础/24-call、apply 和 bind.md
2021-11-16 17:25:05 +08:00

210 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
title: 24-call、apply 和 bind
publish: true
---
<ArticleTopAd></ArticleTopAd>
## 前言
JS 专门为我们提供了一些方法来改变函数内部的 this 指向。常见的方法有 call()、apply()、bind() 方法。
## call() 方法
### call() 方法的作用
call() 方法的作用:可以**调用**一个函数,与此同时,它还可以改变这个函数内部的 this 指向。
call() 方法的另一个应用:**可以实现继承**。之所以能实现继承,其实是利用了上面的作用。
语法:
```js
fn1.call(想要将this指向哪里, 函数实参1, 函数实参2);
```
备注:第一个参数中,如果不需要改变 this 指向,则传 null。
### call() 方法举例
**举例 1**、通过 call() 调用函数:
```js
const obj1 = {
nickName: 'qianguyihao',
age: 28,
};
function fn1() {
console.log(this);
console.log(this.nickName);
}
fn1.call(this); // this的指向并没有被改变此时相当于 fn1();
```
上方代码的打印结果:
```
window
undefined
```
上面的代码,跟普通的函数调用 `fn1()` 没有区别。
**举例 2**、通过 call() 改变 this 指向:
```js
var obj1 = {
nickName: 'qianguyihao',
age: 28,
};
function fn1(a, b) {
console.log(this);
console.log(this.nickName);
console.log(a + b);
}
fn1.call(obj1, 2, 4); // 先将 this 指向 obj1然后执行 fn1() 函数
```
上方代码的打印结果:
```
obj1
qianguyihao
6
```
**举例 3**、通过 call() 实现继承:
```js
// 给 Father 增加 name 和 age 属性
function Father(myName, myAge) {
this.name = myName;
this.age = myAge;
}
function Son(myName, myAge) {
// 【下面这一行,重要代码】
// 通过这一步,将 father 里面的 this 修改为 Son 里面的 this另外给 Son 加上相应的参数,让 Son 自动拥有 Father 里的属性。最终实现继承
Father.call(this, myName, myAge);
}
const son1 = new Son('千古壹号', 28);
console.log(JSON.stringify(son1));
```
上方代码中,通过 call() 方法,让 Son 继承了 Father 里面的 name 和 age 属性。
打印结果:
```
{"myName":"千古壹号","myAge":28}
```
## apply() 方法
### apply() 方法的作用
apply() 方法的作用:可以**调用**一个函数,与此同时,它还可以改变这个函数内部的 this 指向。这一点,和 call()类似。
apply() 方法的应用: 由于 apply()需要传递数组,所以它有一些巧妙应用,稍后看接下来的应用举例就知道了。
语法:
```js
fn1.apply(想要将this指向哪里, [函数实参1, 函数实参2]);
```
备注:第一个参数中,如果不需要改变 this 指向,则传 null。
到这里可以看出, call() 和 apply() 方法的作用是相同的。唯一的区别在于apply() 里面传入的**实参,必须是数组(或者维数组)**。
### apply() 方法举例
**举例**、通过 apply() 改变 this 指向:
```js
var obj1 = {
nickName: 'qianguyihao',
age: 28,
};
function fn1(a) {
console.log(this);
console.log(this.nickName);
console.log(a);
}
fn1.apply(obj1, ['hello']); // 先将 this 指向 obj1然后执行 fn1() 函数
```
注意上方代码中call() 里面传实参时,需要以数组的形式。即便是传一个实参,也需要传数组。
打印结果:
```
obj1
qianguyihao
hello
```
### apply() 方法的巧妙应用:求数组的最大值
我们知道,如果想要求数组中元素的最大值的时候,数组本身是没有自带方法的。那怎么办呢?
虽然数组里没有获取最大值的方法,但是数值里面有 `Math.max(数字1数字2数字3)` 方法,可以获取**多个数值中的最大值**。 另外,由于 apply() 方法在传递实参时,必须要以数组的形式,所以我们可以 通过 Math.max() 和 apply() 曲线救国。
**举例**:求数组中多个元素的最大值:
```js
const arr1 = [3, 7, 10, 8];
// 下面这一行代码的目的,无需改变 this 指向,所以:第一个参数填 null或者填 Math或者填 this 都可以。严格模式中不让填null。
const maxValue = Math.max.apply(Math, arr1); // 求数组 arr1 中元素的最大值
console.log(maxValue);
const minValue = Math.min.apply(Math, arr1); // 求数组 arr1 中元素的最小值
console.log(minValue);
```
打印结果:
```
10
3
```
## bind() 方法
### bind() 方法的作用
bind() 方法**不会调用函数**,但是可以改变函数内部的 this 指向。
把call()、apply()、bind()这三个方法做一下对比,你会发现:实际开发中, bind() 方法使用得最为频繁。如果有些函数我们不需要立即调用但是又想改变这个函数内部的this指向此时用 bind() 是最为合适的。
语法:
```js
新函数 = fn1.bind(想要将this指向哪里, 函数实参1, 函数实参2);
```
参数:
- 第一个参数:在 fn1 函数运行时,指定 fn1 函数的this 指向。如果不需要改变 this 指向,则传 null。
- 其他参数fn1 函数的实参。
解释:它不会调用 fn1 函数,但会返回 由指定this 和指定实参的**原函数拷贝**。可以看出, bind() 方法是有返回值的。
## 我的公众号
想学习**更多技能**?不妨关注我的微信公众号:**千古壹号**id`qianguyihao`)。
扫一扫,你将发现另一个全新的世界,而这将是一场美丽的意外:
![](https://img.smyhvae.com/20200102.png)