本文已参与「新人创作礼」活动,一起开启掘金创作之路
call(), apply() 和 bind() 这三个函数的方法,可以用来改变函数中 this 绑定的上下文对象。接下来让我们来一起了解一下它们!
1. apply 和 call
apply() 和 call() 这两个方法都会以指定的 this 值来调用函数(即调用函数时,设置函数中 this 绑定的上下文对象)
1.1) apply
apply() 方法接受两个参数。
- 第一个参数:我们想要
this绑定的上下文对象 - 第二个参数:我们想要传递的参数(以数组或类数组对象传入-可以包含任意数量)
通过一个例子,来理解一下:
let a = 1;
let obj = {
a: 2
}
function sayValue(...args) {
console.log(this.a, ...args);
}
sayValue.apply(obj, [3, 4]);
1.2) call
cal() 方法和 apply() 方法的作用一样,只不过传参的形式不同。
- 第一个参数:我们想要
this绑定的上下文对象 - 其余参数:逐个传入
通过一个例子,来理解一下:
let a = 1;
let obj = {
a: 2
}
function sayValue(...args) {
console.log(this.a, ...args);
}
// 要传给函数的参数要逐个传入参数
sayValue.call(obj, 3, 4);
2. bind
2.1) bind 介绍
bind() 方法:创建一个新函数,它的 this 为我们想要 this 绑定的上下文对象,也就是传入的对象(即返回一个 this 绑定了传入对象的新函数)
- 第一个参数:我们想要
this绑定的上下文对象 - 其余参数:逐个传入
通过一个例子,来理解一下:
let a = 1;
let obj = {
a: 2
}
function sayValue(...args) {
console.log(this.a, ...args);
}
let sayObjValue = sayValue.bind(obj, 3, 4);
sayObjValue();
2.2) 手写 bind
Function.prototype.myBind = function(context) {
// 调用 myBind 的不是函数,则抛出异常
if (typeof this !== 'function') {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
const self = this;
// 去除第一个参数---要绑定的对象,留下实际传入的参数
const args = [...arguments].slice(1);
// 创建要返回的新函数
const newFunc = function() {
// 当 myBind 作为一个构造函数的时候,不用改变this的指向
const _this = this instanceof newFunc ? this : context;
// 将传入的参数和返回的函数传入的参数合并
const newArgs = [...args, ...arguments];
self.apply(_this, newArgs);
};
// 当 new 的时候,空对象的原型指向绑定函数的原型
/*
在这里不能直接 newFunc.prototype = this.prototype
如果直接 newFunc.prototype = this.prototype
newFunc.prototype 和 this.prototype 指向同一个内存空间
它们之间的改变就会造成互相影响,这不是我们想要的效果
*/
const Fn = function() {};
Fn.prototype = this.prototype;
newFunc.prototype = new Fn();
return newFunc;
}