手写 call、apply 及 bind 函数
一、介绍
1)call apply bind 功能:重定义 this 对象
bind 返回的是一个新函数,必须调用才会执行
2)参数
var obj = {
name: 'zs',
objAge: this`在这里插入代码片`.age,
myFunc: function (fm, t) {
console.log(this.name + '年龄:' + this.age + ' 来自 ' + fm + ' 去往 ' + t);
}
}
var db ={
name: 'dd',
age: 34
}
a. 第一个参数都是 this 指向的对象
b. 第二个参数
call 的参数是直接放入,以逗号分隔,后面的 n 个参数也是直接放到后面
obj.myFunc.call(db, 'a', 'b'); // dd年龄:34 来自 a 去往 b
apply 的参数必须放在一个数组里传进去
obj.myFunc.apply(db, ['c', 'd']) // dd年龄:34 来自 c 去往 d
bind 的参数和 call 是一样的
obj.myFunc.bind(db,['e','f'])(); // dd年龄:34 来自 e,f 去往 undefined
obj.myFunc.bind(db,'e','f')(); // dd年龄:34 来自 e 去往 f
二、实现
- call 函数的实现
/**
* 实现步骤
* 1. 判断调用对象是否为函数
* 2. 判断传入上下文对象是否存在,不存在则设置为 window
* 3. 处理传入的参数,截取第一个参数后的所有参数
* 4. 将函数作为上下文对象的一个属性
* 5. 使用上下文对象来调用这个方法,并保存返回结果
* 6. 删除刚才新增的属性
* 7. 返回结果
*/
Function.prototype.myCall = function (context) {
// 1. 判断调用对象是否为函数
if (typeof this !== 'function') {
console.error('type error');
}
// 2. 判断传入上下文对象是否存在,不存在则设置为 window
context = context || globalThis;
// 3. 截取第一个参数后的所有参数
let args = [...arguments].slice(1);
// 4. 将调用函数设为对象的属性
context.fn = this;
// 5. 使用上下文对象来调用这个方法,并保存返回结果
let result = context.fn(...args);
// 6. 删除刚才新增的属性
delete context.fn;
// 7. 返回结果
return result;
}
- apply 函数的实现
/**
* 1. 判断当前操作对象是否为函数
* 2. 判断上下文对象是否存在,不存在则设为 window
* 3. 处理传入的参数,获取第二个参数
* 4. 将调用函数设为上下文对象的属性
* 5. 使用上下文对象执行这个方法,并保存结果
* 6. 删除新增的属性
* 7. 返回结果
*/
Function.prototype.myApply = function(context) {
// 1. 判断当前操作对象是否为函数
if(typeof this !== 'function') {
console.error('type error');
}
// 2. 判断上下文对象是否存在,不存在则设为 window
context = context || globalThis; // node 设为 globalThis
// 3. 处理传入的参数,获取第二个参数
let args = arguments[1] || [];
// 4. 将调用函数设为上下文对象的属性
context.fn = this;
// 5. 使用上下文对象执行这个方法,并保存结果
let result = context.fn(...args);
// 6. 删除新增的属性
delete context.fn;
// 7. 返回结果
return result;
}
- bind 函数的实现
Function.prototype.myBind = function(context) {
// 1. 判断调用对象是否为函数
if(typeof this !== 'function') {
console.error('type error');
}
// 2. 获取参数
let args = [...arguments].slice(1);
let fn = this;
return function Fn() {
// 3. 根据调用方式,传入不同的绑定值
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
);
}
}