方法 | call | apply | bind |
---|---|---|---|
参 | 多个 | 单个数组 | 多个 |
作用 | 函数调用改变this | 同理 | 同理 |
果 | 直接执行的 | 直接执行的 | 返回待执行函数 |
基本概念
call
、apply
和 bind
是 Function 对象的三个方法,用于改变函数执行时的 this 指向:
javascript
func.call(thisArg, param1, param2, ...)
func.apply(thisArg, [param1, param2, ...])
func.bind(thisArg, param1, param2, ...)
- 在
浏览器
里,在全局范围内this指向window对象
; - 在
函数
中,this
永远指向最后调用
他的那个对象; 构造函数
中,this指向new出来的那个新的对象
;
call、apply、bind
中的this被强绑定在指定的那个对象上;- 箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
apply、call、bind
都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参。
this 指向规则
- 全局范围内:this 指向 window 对象
- 函数中:this 指向最后调用它的对象
- 构造函数中:this 指向 new 出来的新对象
- call/apply/bind:this 被强绑定在指定对象上
- 箭头函数:this 为父作用域的 this(静态绑定)
方法区别
方法 | 参数形式 | 执行时机 | 返回值 |
---|---|---|---|
call | 参数列表 | 立即执行 | 函数返回值 |
apply | 参数数组 | 立即执行 | 函数返回值 |
bind | 参数列表 | 不立即执行 | 返回绑定函数 |
应用场景
1. 判断数据类型
javascript
function getType(obj) {
let type = typeof obj;
if (type !== "object") return type;
return Object.prototype.toString.call(obj).replace(/^$/, '$1');
}
2. 类数组借用数组方法
javascript
var arrayLike = {
0: 'java',
1: 'script',
length: 2
}
Array.prototype.push.call(arrayLike, 'jack', 'lily');
// {0: "java", 1: "script", 2: "jack", 3: "lily", length: 4}
3. 获取数组最大/最小值
javascript
let arr = [13, 6, 10, 11, 16];
const max = Math.max.apply(Math, arr);
const min = Math.min.apply(Math, arr);
手动实现
实现 bind
javascript
Function.prototype.myBind = function(context) {
if (typeof this !== 'function') throw new TypeError('Error');
const _this = this;
const args = [...arguments].slice(1);
return function F() {
if (this instanceof F) {
return new _this(...args, ...arguments);
}
return _this.apply(context, args.concat(...arguments));
}
}
实现 call
javascript
Function.prototype.myCall = function(context) {
context = context || window;
context.fn = this;
const args = [...arguments].slice(1);
const result = context.fn(...args);
delete context.fn;
return result;
}
实现 apply
javascript
Function.prototype.myApply = function(context = window, ...args) {
const key = Symbol('key');
context[key] = this;
const result = context[key](args);
delete context[key];
return result;
}
总结
这三个方法的核心原理都是通过改变函数的 this 指向来实现"借用"方法的功能。在实际开发中,它们常用于:
- 改变函数上下文
- 实现函数借用
- 实现柯里化(bind)
- 处理类数组对象
- 实现更灵活的函数调用方式