call、apply 和 bind 是 JavaScript 中用于控制函数执行上下文(即 this 的值)的三个重要方法。它们的主要作用是允许你显式地指定函数内部的 this 指向。
基础
call
call 方法用于立即调用函数,并指定函数内部的 this 值。它还可以传递参数给函数。
语法:
|
|
thisArg:指定函数执行时的this值。arg1, arg2, ...:传递给函数的参数。
示例:
|
|
在这个例子中,call 将 greet 函数的 this 指向了 anotherPerson,因此 this.name 变成了 "Bob"。
apply
apply 方法与 call 类似,也是用于立即调用函数,并指定函数内部的 this 值。不同的是,apply 传递参数时使用数组形式。
语法:
|
|
thisArg:指定函数执行时的this值。argsArray:传递给函数的参数数组。
示例:
|
|
在这个例子中,apply 将 greet 函数的 this 指向了 anotherPerson,并通过数组传递了参数。
bind
bind 方法不会立即调用函数,而是返回一个新函数,并将 this 绑定到指定的对象。你可以稍后调用这个新函数。
语法:
|
|
thisArg:指定函数执行时的this值。arg1, arg2, ...:传递给函数的参数(可选)。
示例:
|
|
在这个例子中,bind 返回了一个新函数 greetBob,它的 this 被绑定到 anotherPerson,并且预设了参数 "Hello"。
总结对比
| 方法 | 是否立即执行 | 参数传递方式 | 返回值 |
|---|---|---|---|
call |
是 | 逐个传递(逗号分隔) | 无 |
apply |
是 | 数组形式 | 无 |
bind |
否 | 逐个传递(可选) | 返回一个新函数 |
使用场景
-
call和apply:- 当你需要立即调用一个函数,并指定
this时。 - 例如:借用方法(从一个对象借用方法到另一个对象)。
- 当你需要立即调用一个函数,并指定
-
bind:- 当你需要创建一个新函数,并绑定
this时。 - 例如:事件处理函数、回调函数。
- 当你需要创建一个新函数,并绑定
示例:借用方法
|
|
在这个例子中,Math.max 方法通常接受多个参数,但通过 apply,我们可以将数组作为参数传递。
注意事项
-
thisArg为null或undefined:- 如果
thisArg为null或undefined,this将指向全局对象(在浏览器中是window)。
- 如果
-
bind的永久绑定:- 一旦使用
bind绑定this,后续无法通过call或apply改变this的值。
- 一旦使用
通过掌握 call、apply 和 bind,你可以更灵活地控制函数的行为,尤其是在处理对象方法和回调函数时非常有用。
附录
如何理解“bind 的永久绑定”?
❓问:如何理解“一旦使用 bind 绑定 this,后续无法通过 call 或 apply 改变 this 的值” ?
❗答: bind 的实现原理是创建一个新的函数,并将 this 硬编码到这个新函数中。因此,无论你如何调用这个新函数,它的 this 值都不会改变。
下面让我们看一下其 「底层原理 」:
当你使用 bind 时,JavaScript 引擎会生成一个新的函数,类似于以下伪代码:
|
|
其中:
boundThis是bind绑定的对象。originalFunction是原始函数。
在这个新函数中,this 已经被硬编码为 boundThis,因此无法通过 call 或 apply 改变。
❓问:那可不可以再次使用 bind 改变 this 的指向呢?
❗答:不可以! bind 的绑定是不可变的:即使你多次使用 bind,也不会覆盖之前的绑定。
这种特性使得 bind 非常适合用于创建回调函数或事件处理函数,因为你可以确保 this 的值在任何情况下都不会改变。