JavaScript 中 call()、apply()、bind() 的用法

JavaScript中call、apply、bind的区别与用法(案例详解)

通过简单的代码案例理解 callapplybind 的核心区别,并总结三者的使用场景和用法,重点聚焦 this 指向的改变和参数传递的差异。本文通过分步案例拆解核心逻辑,让三者的区别一目了然。

一、前置知识:理解this的默认指向

在学习 call/apply/bind 前,先明确 this 的默认指向规则,这是理解三者作用的基础。

案例1:对象方法中的this

1
2
3
4
5
6
7
8
9
10
11
var name = '小王', age = 20;
var obj = {
name: '小张',
objAge: this.age, // 此处this指向全局window
myFun: function() {
console.log(this.name + '年龄' + this.age); // 此处this指向obj
}
}

console.log(obj.objAge); // 20(window.age)
console.log(obj.myFun()); // 小张年龄 undefined(obj无age属性)

核心结论:对象内部的普通方法中,this 指向调用该方法的对象(此处为 obj);对象属性初始化时,this 指向全局 window(浏览器环境)。

案例2:全局函数中的this

1
2
3
4
5
6
var name = '小陈';
function showName() {
console.log(this.name); // 此处this指向全局window
}

showName(); // 小陈(window.name)

核心结论:全局声明的函数直接调用时,this 指向全局 window(浏览器环境)。

二、核心功能:call/apply/bind 改变this指向

三者的核心作用是手动修改函数执行时的this指向,第一个参数即为新的this指向对象。

案例演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var name = '小王', age = 20;
var obj = {
name: '小张',
objAge: this.age,
myFun: function() {
console.log(this.name + '年龄' + this.age);
}
}
var db = { // 目标this指向的对象
name: '小陈',
age: 99
}

obj.myFun.call(db); // 小陈年龄 99(立即执行)
obj.myFun.apply(db); // 小陈年龄 99(立即执行)
obj.myFun.bind(db)(); // 小陈年龄 99(bind返回新函数,需调用才执行)

核心差异(执行时机)

  • call/apply立即执行函数,修改this后直接运行;
  • bind返回一个绑定了新this的新函数,不会立即执行,需手动加 () 调用。

三、关键差异:参数传递方式

当函数需要传参时,三者的参数传递规则不同,这是最易混淆的点。

案例演示(带参函数)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
var name = '小王', age = 20;
var obj = {
name: '小张',
myFun: function(fm, t) {
console.log(this.name + '年龄' + this.age, '来自' + fm + '去往' + t);
}
}
var db = {
name: '小陈',
age: 99
}

// 1. call:逐个传递参数(新this + 参数1 + 参数2 + ...)
obj.myFun.call(db, '成都', '上海'); // 小陈年龄 99 来自成都去往上海

// 2. apply:数组传递参数(新this + [参数1, 参数2, ...])
obj.myFun.apply(db, ['成都', '上海']); // 小陈年龄 99 来自成都去往上海

// 3. bind:参数传递同call,返回新函数后执行
obj.myFun.bind(db, '成都', '上海')(); // 小陈年龄 99 来自成都去往上海
obj.myFun.bind(db, ['成都', '上海'])(); // 小陈年龄 99 来自成都,上海去往undefined(数组被当作单个参数)

参数规则总结

方法 参数传递方式 执行时机
call func.call(新this, 参数1, 参数2, ...) 立即执行
apply func.apply(新this, [参数1, 参数2]) 立即执行
bind func.bind(新this, 参数1, 参数2, ...) 返回新函数,需手动调用

补充:apply 的第二个参数可以是任意类数组(如 argumentsNodeList),不一定是纯数组。

四、核心总结

1. 相同点

  • 三者均可修改函数执行时的this指向,第一个参数为新的this对象(若传 null/undefined,this仍指向window);
  • 均可传递额外参数。

2. 不同点

维度 call apply bind
参数传递 逐个传参 数组/类数组传参 逐个传参
执行时机 立即执行 立即执行 返回新函数,需手动调用
适用场景 参数数量固定 参数数量不固定/类数组 需复用绑定this的函数

3. 典型使用场景

  • call:快速调用函数并传固定参数(如继承、借用方法 Array.prototype.slice.call(类数组));
  • apply:参数为数组时(如求数组最大值 Math.max.apply(Math, [1,2,3]));
  • bind:需要绑定this后延迟执行(如事件回调、定时器中固定this指向)。

参考资料

关键点回顾

  1. call/apply/bind 的核心是修改函数的 this 指向,第一个参数为新的this对象;
  2. call/apply 立即执行,bind 返回新函数需手动调用;
  3. 参数传递:call 逐个传、apply 数组传、bindcall

JavaScript 中 call()、apply()、bind() 的用法
https://cszy.top/20201015-js-call-apply-bind/
作者
csorz
发布于
2020年10月15日
许可协议