1、call方法
一、call函数的定义:Function 实例的 call() 方法会以给定的 this 值和逐个提供的参数调用该函数。直接上代码:
// 自定义call方法
function _call(target, ...arg) {
if (!target) {
// target对象为null或者undefined时,赋值为全局对象(nodejs为global)
target = window;
}
// 定义一个symbol类型的变量来作为对象的键
// 这样做的好处是,避免了出现同名属性时,属性值被覆盖的问题
let symbol = Symbol();
target[symbol] = this;
let result = target[symbol](...arg);
delete target[symbol];
return result;
}
Function.prototype._call = _call;
var name = 'window';
var obj = {
name: 'obj',
}
function print(a, b, c) {
console.log(this.name, a, b, c);
}
print._call(obj, '1', '2', '3'); // obj 1 2 3
2、apply方法
一、apply函数的定义:Function 实例的 apply() 方法会以给定的 this 值和作为数组(或类数组对象)提供的 arguments 调用该函数。直接上代码:
// 自定义apply方法
function _apply(target, arg) {
if (!target) {
// target对象为null或者undefined时,赋值为全局对象(nodejs为global)
target = window;
}
// 处理arg参数
// 由于该参数可以是类数组对象,因此,我们先将其处理为数组对象
let input = Array.from(arg);
// 定义一个symbol类型的变量来作为对象的键
// 这样做的好处是,避免了出现同名属性时,属性值被覆盖的问题
let symbol = Symbol();
target[symbol] = this;
let result = target[symbol](...input);
delete target[symbol];
return result;
}
Function.prototype._apply = _apply;
var name = 'window';
var obj = {
name: 'obj',
}
function print(a, b, c) {
console.log(this.name, a, b, c);
}
print._apply(obj, ['1', '2', '3']); // obj 1 2 3
tips:Array.from()
3、bind方法
一、bind函数的定义:Function 实例的 bind() 方法创建一个新函数,当调用该新函数时,它会调用原始函数并将其 this 关键字设置为给定的值,同时,还可以传入一系列指定的参数,这些参数会插入到调用新函数时传入的参数的前面。直接上代码:
// 自定义bind方法
function _bind(target, ...arg) {
if (!target) {
// target对象为null或者undefined时,赋值为全局对象(nodejs为global)
target = window;
}
// 保留需要被绑定的函数引用
let _this = this;
let bindFunc = function (..._arg) {
// 监测函数是否使用new关键字调用,不懂的同学请自行查看MDN
if (!new.target) {
// 此处也可以使用我们手写的call
return _this.call(target, ...arg, ..._arg);
} else {
// 使用new关键字调用绑定后的函数,则this指向new关键字创建的新对象
// 具体可以参考本人的博客 https://blog.csdn.net/m0_63422186/article/details/130160636
return _this.call(this, ...arg, ..._arg);
}
}
return bindFunc;
}
Function.prototype._bind = _bind;
var name = 'window';
var obj = {
name: 'obj',
}
function print(...arg) {
console.log(this.name, ...arg);
}
let func = print._bind(obj, 0, 0, 0);
func(1, 2, 3); // obj 0 0 0 1 2 3
let newObj = new func('a', 'b', 'c'); // undefined 0 0 0 a b c
总结
- call、apply以及bind方法都是改变函数执行时内部this指向。
- 调用call以及apply方法都是立即执行,而调用bind方法返回一个新的函数,新函数内部的this指向绑定时传入对象。
- call函数与apply函数的区别就是它们传入参数的方式不同。
座右铭
天下难事,必作于易;天下大事,必做于细。